{- |
    Module      :  $Header$
    Description :  Extraction of free qualified annotated variables
    Copyright   :  (c) 2017        Finn Teegen
    License     :  BSD-3-clause

    Maintainer  :  bjp@informatik.uni-kiel.de
    Stability   :  experimental
    Portability :  portable

    TODO
-}
module Base.AnnotExpr (QualAnnotExpr (..)) where

import qualified Data.Set  as Set (fromList, notMember)

import Curry.Base.Ident
import Curry.Base.SpanInfo
import Curry.Syntax

import Base.Expr
import Base.Types
import Base.Typing

class QualAnnotExpr e where
  -- |Free qualified annotated variables in an 'Expr'
  qafv :: ModuleIdent -> e Type -> [(Type, Ident)]

-- The 'Decl' instance of 'QualAnnotExpr' returns all free
-- variables on the right hand side, regardless of whether they are bound
-- on the left hand side. This is more convenient as declarations are
-- usually processed in a declaration group where the set of free
-- variables cannot be computed independently for each declaration.

instance QualAnnotExpr Decl where
  qafv :: ModuleIdent -> Decl Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (FunctionDecl  _ _ _ eqs :: [Equation Type]
eqs) = (Equation Type -> [(Type, Ident)])
-> [Equation Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Equation Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Equation Type]
eqs
  qafv m :: ModuleIdent
m (PatternDecl     _ _ rhs :: Rhs Type
rhs) = ModuleIdent -> Rhs Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Rhs Type
rhs
  qafv m :: ModuleIdent
m (ClassDecl    _ _ _ _ ds :: [Decl Type]
ds) = (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds
  qafv m :: ModuleIdent
m (InstanceDecl _ _ _ _ ds :: [Decl Type]
ds) = (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds
  qafv _ _                         = []

instance QualAnnotExpr Equation where
  qafv :: ModuleIdent -> Equation Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (Equation _ lhs :: Lhs Type
lhs rhs :: Rhs Type
rhs) = Lhs Type -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv Lhs Type
lhs ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ ModuleIdent -> Lhs Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Lhs Type
lhs [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Rhs Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Rhs Type
rhs

instance QualAnnotExpr Lhs where
  qafv :: ModuleIdent -> Lhs Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m = (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) ([Pattern Type] -> [(Type, Ident)])
-> (Lhs Type -> [Pattern Type]) -> Lhs Type -> [(Type, Ident)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ident, [Pattern Type]) -> [Pattern Type]
forall a b. (a, b) -> b
snd ((Ident, [Pattern Type]) -> [Pattern Type])
-> (Lhs Type -> (Ident, [Pattern Type]))
-> Lhs Type
-> [Pattern Type]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lhs Type -> (Ident, [Pattern Type])
forall a. Lhs a -> (Ident, [Pattern a])
flatLhs

instance QualAnnotExpr Rhs where
  qafv :: ModuleIdent -> Rhs Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (SimpleRhs _ e :: Expression Type
e ds :: [Decl Type]
ds) = [Decl Type] -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv [Decl Type]
ds ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds
  qafv m :: ModuleIdent
m (GuardedRhs _ es :: [CondExpr Type]
es ds :: [Decl Type]
ds) =
    [Decl Type] -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv [Decl Type]
ds ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ (CondExpr Type -> [(Type, Ident)])
-> [CondExpr Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> CondExpr Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [CondExpr Type]
es [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds

instance QualAnnotExpr CondExpr where
  qafv :: ModuleIdent -> CondExpr Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (CondExpr _ g :: Expression Type
g e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
g [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e

instance QualAnnotExpr Expression where
  qafv :: ModuleIdent -> Expression Type -> [(Type, Ident)]
qafv _ (Literal             _ _ _) = []
  qafv m :: ModuleIdent
m (Variable           _ ty :: Type
ty v :: QualIdent
v) =
    [(Type, Ident)]
-> (Ident -> [(Type, Ident)]) -> Maybe Ident -> [(Type, Ident)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Type, Ident) -> [(Type, Ident)]
forall (m :: * -> *) a. Monad m => a -> m a
return ((Type, Ident) -> [(Type, Ident)])
-> (Ident -> (Type, Ident)) -> Ident -> [(Type, Ident)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\v' :: Ident
v' -> (Type
ty, Ident
v'))) (Maybe Ident -> [(Type, Ident)]) -> Maybe Ident -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ ModuleIdent -> QualIdent -> Maybe Ident
localIdent ModuleIdent
m QualIdent
v
  qafv _ (Constructor         _ _ _) = []
  qafv m :: ModuleIdent
m (Paren                 _ e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Typed               _ e :: Expression Type
e _) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Record           _ _ _ fs :: [Field (Expression Type)]
fs) = (Field (Expression Type) -> [(Type, Ident)])
-> [Field (Expression Type)] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Field (Expression Type) -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> Field (e Type) -> [(Type, Ident)]
qafvField ModuleIdent
m) [Field (Expression Type)]
fs
  qafv m :: ModuleIdent
m (RecordUpdate       _ e :: Expression Type
e fs :: [Field (Expression Type)]
fs) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ (Field (Expression Type) -> [(Type, Ident)])
-> [Field (Expression Type)] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Field (Expression Type) -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> Field (e Type) -> [(Type, Ident)]
qafvField ModuleIdent
m) [Field (Expression Type)]
fs
  qafv m :: ModuleIdent
m (Tuple                _ es :: [Expression Type]
es) = (Expression Type -> [(Type, Ident)])
-> [Expression Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Expression Type]
es
  qafv m :: ModuleIdent
m (List               _ _ es :: [Expression Type]
es) = (Expression Type -> [(Type, Ident)])
-> [Expression Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Expression Type]
es
  qafv m :: ModuleIdent
m (ListCompr          _ e :: Expression Type
e qs :: [Statement Type]
qs) = (Statement Type -> [(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [Statement Type] -> [(Type, Ident)]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ModuleIdent -> Statement Type -> [(Type, Ident)] -> [(Type, Ident)]
qafvStmt ModuleIdent
m) (ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e) [Statement Type]
qs
  qafv m :: ModuleIdent
m (EnumFrom              _ e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (EnumFromThen      _ e1 :: Expression Type
e1 e2 :: Expression Type
e2) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2
  qafv m :: ModuleIdent
m (EnumFromTo        _ e1 :: Expression Type
e1 e2 :: Expression Type
e2) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2
  qafv m :: ModuleIdent
m (EnumFromThenTo _ e1 :: Expression Type
e1 e2 :: Expression Type
e2 e3 :: Expression Type
e3) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e3
  qafv m :: ModuleIdent
m (UnaryMinus            _ e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Apply             _ e1 :: Expression Type
e1 e2 :: Expression Type
e2) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2
  qafv m :: ModuleIdent
m (InfixApply     _ e1 :: Expression Type
e1 op :: InfixOp Type
op e2 :: Expression Type
e2) = ModuleIdent -> InfixOp Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m InfixOp Type
op [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2
  qafv m :: ModuleIdent
m (LeftSection        _ e :: Expression Type
e op :: InfixOp Type
op) = ModuleIdent -> InfixOp Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m InfixOp Type
op [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (RightSection       _ op :: InfixOp Type
op e :: Expression Type
e) = ModuleIdent -> InfixOp Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m InfixOp Type
op [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Lambda             _ ts :: [Pattern Type]
ts e :: Expression Type
e) = [Pattern Type] -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv [Pattern Type]
ts ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Let                _ ds :: [Decl Type]
ds e :: Expression Type
e) =
    [Decl Type] -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv [Decl Type]
ds ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (Do                _ sts :: [Statement Type]
sts e :: Expression Type
e) = (Statement Type -> [(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [Statement Type] -> [(Type, Ident)]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ModuleIdent -> Statement Type -> [(Type, Ident)] -> [(Type, Ident)]
qafvStmt ModuleIdent
m) (ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e) [Statement Type]
sts
  qafv m :: ModuleIdent
m (IfThenElse     _ e1 :: Expression Type
e1 e2 :: Expression Type
e2 e3 :: Expression Type
e3) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e2 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e3
  qafv m :: ModuleIdent
m (Case           _ _ e :: Expression Type
e alts :: [Alt Type]
alts) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ (Alt Type -> [(Type, Ident)]) -> [Alt Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Alt Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Alt Type]
alts

qafvField :: QualAnnotExpr e => ModuleIdent -> Field (e Type) -> [(Type, Ident)]
qafvField :: ModuleIdent -> Field (e Type) -> [(Type, Ident)]
qafvField m :: ModuleIdent
m (Field _ _ t :: e Type
t) = ModuleIdent -> e Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m e Type
t

qafvStmt :: ModuleIdent -> Statement Type -> [(Type, Ident)] -> [(Type, Ident)]
qafvStmt :: ModuleIdent -> Statement Type -> [(Type, Ident)] -> [(Type, Ident)]
qafvStmt m :: ModuleIdent
m st :: Statement Type
st fvs :: [(Type, Ident)]
fvs = ModuleIdent -> Statement Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Statement Type
st [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ Statement Type -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv Statement Type
st [(Type, Ident)]
fvs

instance QualAnnotExpr Statement where
  qafv :: ModuleIdent -> Statement Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (StmtExpr   _ e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e
  qafv m :: ModuleIdent
m (StmtDecl  _ ds :: [Decl Type]
ds) = [Decl Type] -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv [Decl Type]
ds ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ (Decl Type -> [(Type, Ident)]) -> [Decl Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Decl Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Decl Type]
ds
  qafv m :: ModuleIdent
m (StmtBind _ _ e :: Expression Type
e) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Expression Type
e

instance QualAnnotExpr Alt where
  qafv :: ModuleIdent -> Alt Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (Alt _ t :: Pattern Type
t rhs :: Rhs Type
rhs) = Pattern Type -> [(Type, Ident)] -> [(Type, Ident)]
forall e. QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv Pattern Type
t ([(Type, Ident)] -> [(Type, Ident)])
-> [(Type, Ident)] -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ ModuleIdent -> Rhs Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Rhs Type
rhs

instance QualAnnotExpr InfixOp where
  qafv :: ModuleIdent -> InfixOp Type -> [(Type, Ident)]
qafv m :: ModuleIdent
m (InfixOp    ty :: Type
ty op :: QualIdent
op) = ModuleIdent -> Expression Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m (Expression Type -> [(Type, Ident)])
-> Expression Type -> [(Type, Ident)]
forall a b. (a -> b) -> a -> b
$ SpanInfo -> Type -> QualIdent -> Expression Type
forall a. SpanInfo -> a -> QualIdent -> Expression a
Variable SpanInfo
NoSpanInfo Type
ty QualIdent
op
  qafv _ (InfixConstr _ _ ) = []

instance QualAnnotExpr Pattern where
  qafv :: ModuleIdent -> Pattern Type -> [(Type, Ident)]
qafv _ (LiteralPattern           _ _ _) = []
  qafv _ (NegativePattern          _ _ _) = []
  qafv _ (VariablePattern          _ _ _) = []
  qafv m :: ModuleIdent
m (ConstructorPattern    _ _ _ ts :: [Pattern Type]
ts) = (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Pattern Type]
ts
  qafv m :: ModuleIdent
m (InfixPattern       _ _ t1 :: Pattern Type
t1 _ t2 :: Pattern Type
t2) = ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Pattern Type
t1 [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++ ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Pattern Type
t2
  qafv m :: ModuleIdent
m (ParenPattern               _ t :: Pattern Type
t) = ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Pattern Type
t
  qafv m :: ModuleIdent
m (RecordPattern         _ _ _ fs :: [Field (Pattern Type)]
fs) = (Field (Pattern Type) -> [(Type, Ident)])
-> [Field (Pattern Type)] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Field (Pattern Type) -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> Field (e Type) -> [(Type, Ident)]
qafvField ModuleIdent
m) [Field (Pattern Type)]
fs
  qafv m :: ModuleIdent
m (TuplePattern              _ ts :: [Pattern Type]
ts) = (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Pattern Type]
ts
  qafv m :: ModuleIdent
m (ListPattern             _ _ ts :: [Pattern Type]
ts) = (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Pattern Type]
ts
  qafv m :: ModuleIdent
m (AsPattern                _ _ t :: Pattern Type
t) = ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Pattern Type
t
  qafv m :: ModuleIdent
m (LazyPattern                _ t :: Pattern Type
t) = ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m Pattern Type
t
  qafv m :: ModuleIdent
m (FunctionPattern      _ ty :: Type
ty f :: QualIdent
f ts :: [Pattern Type]
ts) =
    [(Type, Ident)]
-> (Ident -> [(Type, Ident)]) -> Maybe Ident -> [(Type, Ident)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Type, Ident) -> [(Type, Ident)]
forall (m :: * -> *) a. Monad m => a -> m a
return ((Type, Ident) -> [(Type, Ident)])
-> (Ident -> (Type, Ident)) -> Ident -> [(Type, Ident)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\f' :: Ident
f' -> (Type
ty', Ident
f'))) (ModuleIdent -> QualIdent -> Maybe Ident
localIdent ModuleIdent
m QualIdent
f) [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++
      (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Pattern Type]
ts
    where ty' :: Type
ty' = (Type -> Type -> Type) -> Type -> [Type] -> Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Type -> Type -> Type
TypeArrow Type
ty ([Type] -> Type) -> [Type] -> Type
forall a b. (a -> b) -> a -> b
$ (Pattern Type -> Type) -> [Pattern Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Pattern Type -> Type
forall a. Typeable a => a -> Type
typeOf [Pattern Type]
ts
  qafv m :: ModuleIdent
m (InfixFuncPattern _ ty :: Type
ty t1 :: Pattern Type
t1 op :: QualIdent
op t2 :: Pattern Type
t2) =
    [(Type, Ident)]
-> (Ident -> [(Type, Ident)]) -> Maybe Ident -> [(Type, Ident)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((Type, Ident) -> [(Type, Ident)]
forall (m :: * -> *) a. Monad m => a -> m a
return ((Type, Ident) -> [(Type, Ident)])
-> (Ident -> (Type, Ident)) -> Ident -> [(Type, Ident)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\op' :: Ident
op' -> (Type
ty', Ident
op'))) (ModuleIdent -> QualIdent -> Maybe Ident
localIdent ModuleIdent
m QualIdent
op) [(Type, Ident)] -> [(Type, Ident)] -> [(Type, Ident)]
forall a. [a] -> [a] -> [a]
++
      (Pattern Type -> [(Type, Ident)])
-> [Pattern Type] -> [(Type, Ident)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ModuleIdent -> Pattern Type -> [(Type, Ident)]
forall (e :: * -> *).
QualAnnotExpr e =>
ModuleIdent -> e Type -> [(Type, Ident)]
qafv ModuleIdent
m) [Pattern Type
t1, Pattern Type
t2]
    where ty' :: Type
ty' = (Type -> Type -> Type) -> Type -> [Type] -> Type
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Type -> Type -> Type
TypeArrow Type
ty ([Type] -> Type) -> [Type] -> Type
forall a b. (a -> b) -> a -> b
$ (Pattern Type -> Type) -> [Pattern Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Pattern Type -> Type
forall a. Typeable a => a -> Type
typeOf [Pattern Type
t1, Pattern Type
t2]

filterBv :: QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv :: e -> [(Type, Ident)] -> [(Type, Ident)]
filterBv e :: e
e = ((Type, Ident) -> Bool) -> [(Type, Ident)] -> [(Type, Ident)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Ident -> Set Ident -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` [Ident] -> Set Ident
forall a. Ord a => [a] -> Set a
Set.fromList (e -> [Ident]
forall e. QuantExpr e => e -> [Ident]
bv e
e)) (Ident -> Bool)
-> ((Type, Ident) -> Ident) -> (Type, Ident) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Type, Ident) -> Ident
forall a b. (a, b) -> b
snd)