module Language.Haskell.Exts.Build (
    
    name,       
    sym,        
    var,        
    op,         
    qvar,       
    pvar,       
    app,        
    infixApp,   
    appFun,     
    pApp,       
    tuple,      
    pTuple,     
    varTuple,   
    pvarTuple,  
    function,   
    strE,       
    charE,      
    intE,       
    strP,       
    charP,      
    intP,       
    doE,        
    lamE,       
    letE,       
    caseE,      
    alt,        
    altGW,      
    listE,      
    eList,      
    peList,     
    paren,      
    pParen,     
    qualStmt,   
    genStmt,    
    letStmt,    
    binds,      
    noBinds,    
    wildcard,   
    genNames,   
    
    sfun,           
    simpleFun,      
    patBind,        
    patBindWhere,   
    nameBind,       
    metaFunction,   
    metaConPat      
  ) where
import Language.Haskell.Exts.Syntax
name :: String -> Name
name = Ident
sym :: String -> Name
sym = Symbol
var :: Name -> Exp
var = Var . UnQual
op :: Name -> QOp
op = QVarOp . UnQual
qvar :: ModuleName -> Name -> Exp
qvar m n = Var $ Qual m n
pvar :: Name -> Pat
pvar = PVar
app :: Exp -> Exp -> Exp
app = App
infixApp :: Exp -> QOp -> Exp -> Exp
infixApp = InfixApp
appFun :: Exp -> [Exp] -> Exp
appFun f [] = f
appFun f (a:as) = appFun (app f a) as
pApp :: Name -> [Pat] -> Pat
pApp n ps = PApp (UnQual n) ps
tuple :: [Exp] -> Exp
tuple = Tuple Boxed
pTuple :: [Pat] -> Pat
pTuple = PTuple Boxed
varTuple :: [Name] -> Exp
varTuple ns = tuple $ map var ns
pvarTuple :: [Name] -> Pat
pvarTuple ns = pTuple $ map pvar ns
function :: String -> Exp
function = var . Ident
strE :: String -> Exp
strE = Lit . String
charE :: Char -> Exp
charE = Lit . Char
intE :: Integer -> Exp
intE = Lit . Int
strP :: String -> Pat
strP = PLit . String
charP :: Char -> Pat
charP = PLit . Char
intP :: Integer -> Pat
intP = PLit . Int
doE :: [Stmt] -> Exp
doE = Do
lamE :: SrcLoc -> [Pat] -> Exp -> Exp
lamE = Lambda
letE :: [Decl] -> Exp -> Exp
letE ds e = Let (binds ds) e
caseE :: Exp -> [Alt] -> Exp
caseE = Case
alt :: SrcLoc -> Pat -> Exp -> Alt
alt s p e = Alt s p (unGAlt e) noBinds
altGW :: SrcLoc -> Pat -> [Stmt] -> Exp -> Binds -> Alt
altGW s p gs e w = Alt s p (gAlt s gs e) w
unGAlt :: Exp -> GuardedAlts
unGAlt = UnGuardedAlt
gAlts :: SrcLoc -> [([Stmt],Exp)] -> GuardedAlts
gAlts s as = GuardedAlts $ map (\(gs,e) -> GuardedAlt s gs e) as
gAlt :: SrcLoc -> [Stmt] -> Exp -> GuardedAlts
gAlt s gs e = gAlts s [(gs,e)]
listE :: [Exp] -> Exp
listE = List
eList :: Exp
eList = List []
peList :: Pat
peList = PList []
paren :: Exp -> Exp
paren = Paren
pParen :: Pat -> Pat
pParen = PParen
qualStmt :: Exp -> Stmt
qualStmt = Qualifier
genStmt :: SrcLoc -> Pat -> Exp -> Stmt
genStmt = Generator
letStmt :: [Decl] -> Stmt
letStmt ds = LetStmt $ binds ds
binds :: [Decl] -> Binds
binds = BDecls
noBinds :: Binds
noBinds = binds []
wildcard :: Pat
wildcard = PWildCard
genNames :: String -> Int -> [Name]
genNames s k = [ Ident $ s ++ show i | i <- [1..k] ]
sfun :: SrcLoc -> Name -> [Name] -> Rhs -> Binds -> Decl
sfun s f pvs rhs bs = FunBind [Match s f (map pvar pvs) Nothing rhs bs]
simpleFun :: SrcLoc -> Name -> Name -> Exp -> Decl
simpleFun s f a e = let rhs = UnGuardedRhs e
             in sfun s f [a] rhs noBinds
patBind :: SrcLoc -> Pat -> Exp -> Decl
patBind s p e = let rhs = UnGuardedRhs e
         in PatBind s p Nothing rhs noBinds
patBindWhere :: SrcLoc -> Pat -> Exp -> [Decl] -> Decl
patBindWhere s p e ds = let rhs = UnGuardedRhs e
             in PatBind s p Nothing rhs (binds ds)
nameBind :: SrcLoc -> Name -> Exp -> Decl
nameBind s n e = patBind s (pvar n) e
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
metaConPat :: String -> [Pat] -> Pat
metaConPat s ps = pApp (name s) ps