{- | 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.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 m (FunctionDecl _ _ _ eqs) = concatMap (qafv m) eqs qafv m (PatternDecl _ _ rhs) = qafv m rhs qafv m (ClassDecl _ _ _ _ ds) = concatMap (qafv m) ds qafv m (InstanceDecl _ _ _ _ ds) = concatMap (qafv m) ds qafv _ _ = [] instance QualAnnotExpr Equation where qafv m (Equation _ lhs rhs) = filterBv lhs $ qafv m lhs ++ qafv m rhs instance QualAnnotExpr Lhs where qafv m = concatMap (qafv m) . snd . flatLhs instance QualAnnotExpr Rhs where qafv m (SimpleRhs _ e ds) = filterBv ds $ qafv m e ++ concatMap (qafv m) ds qafv m (GuardedRhs es ds) = filterBv ds $ concatMap (qafv m) es ++ concatMap (qafv m) ds instance QualAnnotExpr CondExpr where qafv m (CondExpr _ g e) = qafv m g ++ qafv m e instance QualAnnotExpr Expression where qafv _ (Literal _ _) = [] qafv m (Variable ty v) = maybe [] (return . (\v' -> (ty, v'))) $ localIdent m v qafv _ (Constructor _ _) = [] qafv m (Paren e) = qafv m e qafv m (Typed e _) = qafv m e qafv m (Record _ _ fs) = concatMap (qafvField m) fs qafv m (RecordUpdate e fs) = qafv m e ++ concatMap (qafvField m) fs qafv m (Tuple es) = concatMap (qafv m) es qafv m (List _ es) = concatMap (qafv m) es qafv m (ListCompr e qs) = foldr (qafvStmt m) (qafv m e) qs qafv m (EnumFrom e) = qafv m e qafv m (EnumFromThen e1 e2) = qafv m e1 ++ qafv m e2 qafv m (EnumFromTo e1 e2) = qafv m e1 ++ qafv m e2 qafv m (EnumFromThenTo e1 e2 e3) = qafv m e1 ++ qafv m e2 ++ qafv m e3 qafv m (UnaryMinus e) = qafv m e qafv m (Apply e1 e2) = qafv m e1 ++ qafv m e2 qafv m (InfixApply e1 op e2) = qafv m op ++ qafv m e1 ++ qafv m e2 qafv m (LeftSection e op) = qafv m op ++ qafv m e qafv m (RightSection op e) = qafv m op ++ qafv m e qafv m (Lambda ts e) = filterBv ts $ qafv m e qafv m (Let ds e) = filterBv ds $ concatMap (qafv m) ds ++ qafv m e qafv m (Do sts e) = foldr (qafvStmt m) (qafv m e) sts qafv m (IfThenElse e1 e2 e3) = qafv m e1 ++ qafv m e2 ++ qafv m e3 qafv m (Case _ e alts) = qafv m e ++ concatMap (qafv m) alts qafvField :: QualAnnotExpr e => ModuleIdent -> Field (e Type) -> [(Type, Ident)] qafvField m (Field _ _ t) = qafv m t qafvStmt :: ModuleIdent -> Statement Type -> [(Type, Ident)] -> [(Type, Ident)] qafvStmt m st fvs = qafv m st ++ filterBv st fvs instance QualAnnotExpr Statement where qafv m (StmtExpr e) = qafv m e qafv m (StmtDecl ds) = filterBv ds $ concatMap (qafv m) ds qafv m (StmtBind _ e) = qafv m e instance QualAnnotExpr Alt where qafv m (Alt _ t rhs) = filterBv t $ qafv m rhs instance QualAnnotExpr InfixOp where qafv m (InfixOp ty op) = qafv m $ Variable ty op qafv _ (InfixConstr _ _ ) = [] instance QualAnnotExpr Pattern where qafv _ (LiteralPattern _ _) = [] qafv _ (NegativePattern _ _) = [] qafv _ (VariablePattern _ _) = [] qafv m (ConstructorPattern _ _ ts) = concatMap (qafv m) ts qafv m (InfixPattern _ t1 _ t2) = qafv m t1 ++ qafv m t2 qafv m (ParenPattern t) = qafv m t qafv m (RecordPattern _ _ fs) = concatMap (qafvField m) fs qafv m (TuplePattern ts) = concatMap (qafv m) ts qafv m (ListPattern _ ts) = concatMap (qafv m) ts qafv m (AsPattern _ t) = qafv m t qafv m (LazyPattern t) = qafv m t qafv m (FunctionPattern ty f ts) = maybe [] (return . (\f' -> (ty', f'))) (localIdent m f) ++ concatMap (qafv m) ts where ty' = foldr TypeArrow ty $ map typeOf ts qafv m (InfixFuncPattern ty t1 op t2) = maybe [] (return . (\op' -> (ty', op'))) (localIdent m op) ++ concatMap (qafv m) [t1, t2] where ty' = foldr TypeArrow ty $ map typeOf [t1, t2] filterBv :: QuantExpr e => e -> [(Type, Ident)] -> [(Type, Ident)] filterBv e = filter ((`Set.notMember` Set.fromList (bv e)) . snd)