haskell-src-exts-1.24.0: src/Language/Haskell/Exts/Build.hs
{-# LANGUAGE Safe #-}
-----------------------------------------------------------------------------
-- |
-- Module : Language.Haskell.Exts.Build
-- Copyright : (c) The GHC Team, 1997-2000,
-- (c) Niklas Broberg 2004
-- License : BSD-style (see the file LICENSE.txt)
--
-- Maintainer : Niklas Broberg, d00nibro@chalmers.se
-- Stability : experimental
-- Portability : portable
--
-- This module contains combinators to use when building
-- Haskell source trees programmatically, as opposed to
-- parsing them from a string. The contents here are quite
-- experimental and will likely receive a lot of attention
-- when the rest has stabilised.
--
-----------------------------------------------------------------------------
module Language.Haskell.Exts.Build (
-- * Syntax building functions
name, -- :: String -> Name ()
sym, -- :: String -> Name ()
var, -- :: Name () -> Exp ()
op, -- :: Name () -> QOp
qvar, -- :: Module -> Name () -> Exp ()
pvar, -- :: Name () -> Pat ()
app, -- :: Exp () -> Exp () -> Exp ()
infixApp, -- :: Exp () -> QOp -> Exp () -> Exp ()
appFun, -- :: Exp () -> [Exp] -> Exp ()
pApp, -- :: Name () -> [Pat] -> Pat ()
tuple, -- :: [Exp] -> Exp ()
pTuple, -- :: [Pat] -> Pat ()
varTuple, -- :: [Name] -> Exp ()
pvarTuple, -- :: [Name] -> Pat ()
function, -- :: String -> Exp ()
strE, -- :: String -> Exp ()
charE, -- :: Char -> Exp ()
intE, -- :: Integer -> Exp ()
strP, -- :: String -> Pat ()
charP, -- :: Char -> Pat ()
intP, -- :: Integer -> Pat ()
doE, -- :: [Stmt] -> Exp ()
lamE, -- :: SrcLoc -> [Pat] -> Exp () -> Exp ()
letE, -- :: [Decl] -> Exp () -> Exp ()
caseE, -- :: Exp () -> [Alt] -> Exp ()
alt, -- :: SrcLoc -> Pat () -> Exp () -> Alt
altGW, -- :: SrcLoc -> Pat () -> [Stmt] -> Exp () -> Binds -> Alt
listE, -- :: [Exp] -> Exp ()
eList, -- :: Exp ()
peList, -- :: Pat ()
paren, -- :: Exp () -> Exp ()
pParen, -- :: Pat () -> Pat ()
qualStmt, -- :: Exp () -> Stmt
genStmt, -- :: SrcLoc -> Pat () -> Exp () -> Stmt
letStmt, -- :: [Decl] -> Stmt
binds, -- :: [Decl] -> Binds
noBinds, -- :: Binds
wildcard, -- :: Pat ()
genNames, -- :: String -> Int -> [Name]
-- * More advanced building
sfun, -- :: SrcLoc -> Name () -> [Name] -> Rhs -> Binds -> Decl ()
simpleFun, -- :: SrcLoc -> Name () -> Name () -> Exp () -> Decl ()
patBind, -- :: SrcLoc -> Pat () -> Exp () -> Decl ()
patBindWhere, -- :: SrcLoc -> Pat () -> Exp () -> [Decl] -> Decl ()
nameBind, -- :: SrcLoc -> Name () -> Exp () -> Decl ()
metaFunction, -- :: String -> [Exp] -> Exp ()
metaConPat -- :: String -> [Pat] -> Pat ()
) where
import Language.Haskell.Exts.Syntax
-----------------------------------------------------------------------------
-- Help functions for Abstract syntax
-- | An identifier with the given string as its name.
-- The string should be a valid Haskell identifier.
name :: String -> Name ()
name = Ident ()
-- | A symbol identifier. The string should be a valid
-- Haskell symbol identifier.
sym :: String -> Name ()
sym = Symbol ()
-- | A local variable as expression.
var :: Name () -> Exp ()
var = Var () . UnQual ()
-- | Use the given identifier as an operator.
op :: Name () -> QOp ()
op = QVarOp () . UnQual ()
-- | A qualified variable as expression.
qvar :: ModuleName () -> Name () -> Exp ()
qvar m n = Var () $ Qual () m n
-- | A pattern variable.
pvar :: Name () -> Pat ()
pvar = PVar ()
-- | Application of expressions by juxtaposition.
app :: Exp () -> Exp () -> Exp ()
app = App ()
-- | Apply an operator infix.
infixApp :: Exp () -> QOp () -> Exp () -> Exp ()
infixApp = InfixApp ()
-- | Apply a function to a list of arguments.
appFun :: Exp () -> [Exp ()] -> Exp ()
appFun f [] = f
appFun f (a:as) = appFun (app f a) as
-- | A constructor pattern, with argument patterns.
pApp :: Name () -> [Pat ()] -> Pat ()
pApp n ps = PApp () (UnQual () n) ps
-- | A tuple expression.
tuple :: [Exp ()] -> Exp ()
tuple = Tuple () Boxed
-- | A tuple pattern.
pTuple :: [Pat ()] -> Pat ()
pTuple = PTuple () Boxed
-- | A tuple expression consisting of variables only.
varTuple :: [Name ()] -> Exp ()
varTuple ns = tuple $ map var ns
-- | A tuple pattern consisting of variables only.
pvarTuple :: [Name ()] -> Pat ()
pvarTuple ns = pTuple $ map pvar ns
-- | A function with a given name.
function :: String -> Exp ()
function = var . Ident ()
-- | A literal string expression.
strE :: String -> Exp ()
strE s = Lit () (String () s s)
-- | A literal character expression.
charE :: Char -> Exp ()
charE c = Lit () (Char () c [c])
-- | A literal integer expression.
intE :: Integer -> Exp ()
intE n = Lit () (Int () n (show n))
-- | A literal string pattern.
strP :: String -> Pat ()
strP s = PLit () (Signless ()) (String () s s)
-- | A literal character pattern.
charP :: Char -> Pat ()
charP x = PLit () (Signless ()) (Char () x [x])
-- | A literal integer pattern.
intP :: Integer -> Pat ()
intP x = PLit ()
(if x >= 0 then Signless () else Negative ())
(Int () (abs x) (show x))
-- | A do block formed by the given statements.
-- The last statement in the list should be
-- a 'Qualifier' expression.
doE :: [Stmt ()] -> Exp ()
doE = Do ()
-- | Lambda abstraction, given a list of argument
-- patterns and an expression body.
lamE :: [Pat ()] -> Exp () -> Exp ()
lamE = Lambda ()
-- | A @let@ ... @in@ block.
letE :: [Decl ()] -> Exp () -> Exp ()
letE ds e = Let () (binds ds) e
-- | A @case@ expression.
caseE :: Exp () -> [Alt ()] -> Exp ()
caseE = Case ()
-- | An unguarded alternative in a @case@ expression.
alt :: Pat () -> Exp () -> Alt ()
alt p e = Alt () p (unGAlt e) noBinds
-- | An alternative with a single guard in a @case@ expression.
altGW :: Pat () -> [Stmt ()] -> Exp () -> Binds () -> Alt ()
altGW p gs e w = Alt () p (gAlt gs e) (Just w)
-- | An unguarded righthand side of a @case@ alternative.
unGAlt :: Exp () -> Rhs ()
unGAlt = UnGuardedRhs ()
-- | An list of guarded righthand sides for a @case@ alternative.
gAlts :: [([Stmt ()],Exp ())] -> Rhs ()
gAlts as = GuardedRhss () $ map (\(gs,e) -> GuardedRhs () gs e) as
-- | A single guarded righthand side for a @case@ alternative.
gAlt :: [Stmt ()] -> Exp () -> Rhs ()
gAlt gs e = gAlts [(gs,e)]
-- | A list expression.
listE :: [Exp ()] -> Exp ()
listE = List ()
-- | The empty list expression.
eList :: Exp ()
eList = List () []
-- | The empty list pattern.
peList :: Pat ()
peList = PList () []
-- | Put parentheses around an expression.
paren :: Exp () -> Exp ()
paren = Paren ()
-- | Put parentheses around a pattern.
pParen :: Pat () -> Pat ()
pParen = PParen ()
-- | A qualifier expression statement.
qualStmt :: Exp () -> Stmt ()
qualStmt = Qualifier ()
-- | A generator statement: /pat/ @<-@ /exp/
genStmt :: Pat () -> Exp () -> Stmt ()
genStmt = Generator ()
-- | A @let@ binding group as a statement.
letStmt :: [Decl ()] -> Stmt ()
letStmt ds = LetStmt () $ binds ds
-- | Hoist a set of declarations to a binding group.
binds :: [Decl ()] -> Binds ()
binds = BDecls ()
-- | An empty binding group.
noBinds :: Maybe (Binds ())
noBinds = Nothing
-- | The wildcard pattern: @_@
wildcard :: Pat ()
wildcard = PWildCard ()
-- | Generate k names by appending numbers 1 through k to a given string.
genNames :: String -> Int -> [Name ()]
genNames s k = [ Ident () $ s ++ show i | i <- [1..k] ]
-------------------------------------------------------------------------------
-- Some more specialised help functions
-- | A function with a single clause
sfun :: Name () -> [Name ()] -> (Rhs ()) -> Maybe (Binds ()) -> Decl ()
sfun f pvs rhs bs = FunBind () [Match () f (map pvar pvs) rhs bs]
-- | A function with a single clause, a single argument, no guards
-- and no where declarations
simpleFun :: Name () -> Name () -> Exp () -> Decl ()
simpleFun f a e = let rhs = UnGuardedRhs () e
in sfun f [a] rhs noBinds
-- | A pattern bind where the pattern is a variable, and where
-- there are no guards and no 'where' clause.
patBind :: Pat () -> Exp () -> Decl ()
patBind p e = let rhs = UnGuardedRhs () e
in PatBind () p rhs noBinds
-- | A pattern bind where the pattern is a variable, and where
-- there are no guards, but with a 'where' clause.
patBindWhere :: Pat () -> Exp () -> [Decl ()] -> Decl ()
patBindWhere p e ds = let rhs = UnGuardedRhs () e
in PatBind () p rhs (if null ds then Nothing else Just (binds ds))
-- | Bind an identifier to an expression.
nameBind :: Name () -> Exp () -> Decl ()
nameBind n e = patBind (pvar n) e
-- | Apply function of a given name to a list of arguments.
metaFunction :: String -> [Exp ()] -> Exp ()
metaFunction s' es' = mf s' (reverse es')
where mf s [] = var $ name s
mf s (e:es) = app (mf s es) e
-- | Apply a constructor of a given name to a list of pattern
-- arguments, forming a constructor pattern.
metaConPat :: String -> [Pat ()] -> Pat ()
metaConPat s ps = pApp (name s) ps