{-# LANGUAGE TemplateHaskell #-}
import Data.Generics.TH
import Data.String.Utils
import Language.Haskell.TH
import System.Exit

import qualified Data.Set as Set

-- This program generates the Data.Generics.TH.VarSet module
-- when this module compiles.  It is not intended to be run.

-- The reason is that Template Haskell can't "reify" under the IO
-- monad.  Thus we need to be running under GHC's typechecker monad.
-- That happens only at compile time.

accVarRef :: Exp -> Set.Set Name -> Set.Set Name
accVarRef = undefined

$(do e <- [d|varSet e = $(everythingForL 'accVarRef [t| Exp |]) e Set.empty|]
     let fileName = "Data/Generics/TH/VarSet.hs"
     runIO $ writeFile fileName $

             "-- Do not edit.  This file is generated by \"util/makeVarSet.hs\".\n" ++
             "{-# OPTIONS_GHC -W -Wall #-}\n" ++
             "module Data.Generics.TH.VarSet (varSet) where\n" ++
             "import Language.Haskell.TH.Syntax\n" ++
             "import GHC.Base\n" ++
             "import qualified Data.Set as Set\n" ++
             "import qualified Data.Maybe\n" ++

             "accVarRef :: Exp -> Set.Set Name -> Set.Set Name\n" ++
             "accVarRef (VarE n) set = Set.insert n set\n" ++
             "accVarRef _        set = set\n" ++

             "varSet :: Exp -> Set.Set Name\n" ++
             (replace "GHC.Tuple." "" $
              replace "GHC.Types." "" $
              replace "Main." "" $
              replace "Data.Set." "Set." $
              (pprint e)) ++
             "\n"

     runIO $ putStrLn $ "Generated " ++ fileName
     return [] {- Return an empty set of declarations. -})

main = putStrLn "Error: this program is intended to be compiled but not run" >> exitFailure
