Miscellaneous utilities on ordinary Haskell syntax used by the arrow
translator.
> module Utils(
> FreeVars(freeVars), DefinedVars(definedVars),
> failureFree, irrPat, paren, parenInfixArg,
> tuple, tupleP,
> times
> ) where
> import Data.Set (Set)
> import qualified Data.Set as Set
> import Language.Haskell.Syntax
The set of free variables in some construct.
> class FreeVars a where
> freeVars :: a -> Set HsName
> instance FreeVars a => FreeVars [a] where
> freeVars = Set.unions . map freeVars
> instance FreeVars HsPat where
> freeVars (HsPVar n) = Set.singleton n
> freeVars (HsPLit _) = Set.empty
> freeVars (HsPNeg p) = freeVars p
> freeVars (HsPInfixApp p1 _ p2) = freeVars p1 `Set.union` freeVars p2
> freeVars (HsPApp _ ps) = freeVars ps
> freeVars (HsPTuple ps) = freeVars ps
> freeVars (HsPList ps) = freeVars ps
> freeVars (HsPParen p) = freeVars p
> freeVars (HsPRec _ pfs) = freeVars pfs
> freeVars (HsPAsPat n p) = Set.insert n (freeVars p)
> freeVars (HsPWildCard) = Set.empty
> freeVars (HsPIrrPat p) = freeVars p
> instance FreeVars HsPatField where
> freeVars (HsPFieldPat _ p) = freeVars p
> instance FreeVars HsFieldUpdate where
> freeVars (HsFieldUpdate _ e) = freeVars e
> instance FreeVars HsExp where
> freeVars (HsVar n) = freeVars n
> freeVars (HsCon _) = Set.empty
> freeVars (HsLit _) = Set.empty
> freeVars (HsInfixApp e1 op e2) =
> freeVars e1 `Set.union` freeVars op `Set.union` freeVars e2
> freeVars (HsApp f e) = freeVars f `Set.union` freeVars e
> freeVars (HsNegApp e) = freeVars e
> freeVars (HsLambda _ ps e) = freeVars e `Set.difference` freeVars ps
> freeVars (HsLet decls e) =
> (freeVars decls `Set.union` freeVars e) `Set.difference`
> definedVars decls
> freeVars (HsIf e1 e2 e3) =
> freeVars e1 `Set.union` freeVars e2 `Set.union` freeVars e3
> freeVars (HsCase e as) = freeVars e `Set.union` freeVars as
> freeVars (HsDo ss) = freeVarsStmts ss
> freeVars (HsTuple es) = freeVars es
> freeVars (HsList es) = freeVars es
> freeVars (HsParen e) = freeVars e
> freeVars (HsLeftSection e op) = freeVars e `Set.union` freeVars op
> freeVars (HsRightSection op e) = freeVars op `Set.union` freeVars e
> freeVars (HsRecConstr _ us) = freeVars us
> freeVars (HsRecUpdate e us) = freeVars e `Set.union` freeVars us
> freeVars (HsEnumFrom e) = freeVars e
> freeVars (HsEnumFromTo e1 e2) = freeVars e1 `Set.union` freeVars e2
> freeVars (HsEnumFromThen e1 e2) = freeVars e1 `Set.union` freeVars e2
> freeVars (HsEnumFromThenTo e1 e2 e3) =
> freeVars e1 `Set.union` freeVars e2 `Set.union` freeVars e3
> freeVars (HsListComp e ss) =
> freeVars e `Set.union` freeVarsStmts ss
> freeVars (HsExpTypeSig _ e _) = freeVars e
> freeVars (HsAsPat _ _) = error "freeVars (x @ p)"
> freeVars (HsWildCard) = error "freeVars _"
> freeVars (HsIrrPat _) = error "freeVars ~p"
> instance FreeVars HsQOp where
> freeVars (HsQVarOp n) = freeVars n
> freeVars (HsQConOp _) = Set.empty
> instance FreeVars HsQName where
> freeVars (UnQual v) = Set.singleton v
> freeVars _ = Set.empty
> instance FreeVars HsAlt where
> freeVars (HsAlt _ p gas decls) =
> (freeVars gas `Set.union` freeVars decls) `Set.difference`
> (freeVars p `Set.union` definedVars decls)
> instance FreeVars HsGuardedAlts where
> freeVars (HsUnGuardedAlt e) = freeVars e
> freeVars (HsGuardedAlts alts) = freeVars alts
> instance FreeVars HsGuardedAlt where
> freeVars (HsGuardedAlt _ e1 e2) = freeVars e1 `Set.union` freeVars e2
> instance FreeVars HsDecl where
> freeVars (HsFunBind ms) = freeVars ms
> freeVars (HsPatBind _ p rhs decls) =
> (freeVars rhs `Set.union` freeVars decls) `Set.difference`
> (freeVars p `Set.union` definedVars decls)
> freeVars _ = Set.empty
> instance FreeVars HsMatch where
> freeVars (HsMatch _ n ps rhs decls) =
> (freeVars rhs `Set.union` freeVars decls) `Set.difference`
> (Set.insert n (freeVars ps) `Set.union` definedVars decls)
> instance FreeVars HsRhs where
> freeVars (HsUnGuardedRhs e) = freeVars e
> freeVars (HsGuardedRhss grs) = freeVars grs
> instance FreeVars HsGuardedRhs where
> freeVars (HsGuardedRhs _ e1 e2) = freeVars e1 `Set.union` freeVars e2
> freeVarsStmts :: [HsStmt] -> Set HsName
> freeVarsStmts = foldr addStmt Set.empty
> where addStmt (HsGenerator _ p e) s =
> freeVars e `Set.union` (s `Set.difference` freeVars p)
> addStmt (HsQualifier e) _s = freeVars e
> addStmt (HsLetStmt decls) s =
> (freeVars decls `Set.union` s) `Set.difference` definedVars decls
The set of variables defined by a construct.
> class DefinedVars a where
> definedVars :: a -> Set HsName
> instance DefinedVars a => DefinedVars [a] where
> definedVars = Set.unions . map definedVars
> instance DefinedVars HsDecl where
> definedVars (HsFunBind (HsMatch _ n _ _ _:_)) = Set.singleton n
> definedVars (HsPatBind _ p _ _) = freeVars p
> definedVars _ = Set.empty
Is the pattern failure-free?
(This is incomplete at the moment, because patterns made with unique
constructors should be failure-free, but we have no way of detecting them.)
> failureFree :: HsPat -> Bool
> failureFree (HsPVar _) = True
> failureFree (HsPApp n ps) = n == unit_con_name && null ps
> failureFree (HsPTuple ps) = all failureFree ps
> failureFree (HsPParen p) = failureFree p
> failureFree (HsPAsPat _ p) = failureFree p
> failureFree (HsPWildCard) = True
> failureFree (HsPIrrPat _) = True
> failureFree _ = False
Irrefutable version of a pattern
> irrPat :: HsPat -> HsPat
> irrPat p@(HsPVar _) = p
> irrPat (HsPParen p) = HsPParen (irrPat p)
> irrPat (HsPAsPat n p) = HsPAsPat n (irrPat p)
> irrPat p@(HsPWildCard) = p
> irrPat p@(HsPIrrPat _) = p
> irrPat p = HsPIrrPat p
Make an expression into an aexp, by adding parentheses if required.
> paren :: HsExp -> HsExp
> paren e = if isAexp e then e else HsParen e
> where isAexp (HsVar _) = True
> isAexp (HsCon _) = True
> isAexp (HsLit _) = True
> isAexp (HsParen _) = True
> isAexp (HsTuple _) = True
> isAexp (HsList _) = True
> isAexp (HsEnumFrom _) = True
> isAexp (HsEnumFromTo _ _) = True
> isAexp (HsEnumFromThen _ _) = True
> isAexp (HsEnumFromThenTo _ _ _) = True
> isAexp (HsListComp _ _) = True
> isAexp (HsLeftSection _ _) = True
> isAexp (HsRightSection _ _) = True
> isAexp (HsRecConstr _ _) = True
> isAexp (HsRecUpdate _ _) = True
> isAexp _ = False
Make an expression into an fexp, by adding parentheses if required.
> parenInfixArg :: HsExp -> HsExp
> parenInfixArg e@(HsApp _ _) = e
> parenInfixArg e = paren e
Tuples
> tuple :: [HsExp] -> HsExp
> tuple [] = unit_con
> tuple [e] = e
> tuple es = HsTuple es
> tupleP :: [HsPat] -> HsPat
> tupleP [] = HsPApp unit_con_name []
> tupleP [e] = e
> tupleP es = HsPTuple es
Compose a function n times.
> times :: Int -> (a -> a) -> a -> a
> times n f a = foldr ($) a (replicate n f)