agda2hs-1.2: src/Agda2Hs/Compile.hs
module Agda2Hs.Compile where
import Control.Monad.Reader ( ReaderT(runReaderT) )
import Control.Monad.Writer ( WriterT(runWriterT) )
import Control.Monad.State ( StateT, evalStateT, get )
import qualified Data.Map as M
import Agda.Compiler.Backend
import Agda.Syntax.TopLevelModuleName ( TopLevelModuleName )
import Agda.TypeChecking.Pretty
import Agda.Utils.Null
import Agda.Utils.Monad ( whenM )
import qualified Language.Haskell.Exts.Extension as Hs
import Agda2Hs.Compile.ClassInstance ( compileInstance )
import Agda2Hs.Compile.Data ( compileData )
import Agda2Hs.Compile.Function ( compileFun, checkTransparentPragma )
import Agda2Hs.Compile.Postulate ( compilePostulate )
import Agda2Hs.Compile.Record ( compileRecord, checkUnboxPragma )
import Agda2Hs.Compile.Types
import Agda2Hs.Compile.Utils ( setCurrentRangeQ, tellExtension )
import Agda2Hs.Pragma
-- Needs a list of rewrite rules too.
initCompileEnv :: TopLevelModuleName -> SpecialRules -> CompileEnv
initCompileEnv tlm rewrites = CompileEnv
{ currModule = tlm
, minRecordName = Nothing
, locals = []
, copatternsEnabled = False
, checkVar = False
, rewrites = rewrites
}
initCompileState :: CompileState
initCompileState = CompileState { lcaseUsed = 0 }
runC :: TopLevelModuleName -> SpecialRules -> C a -> TCM (a, CompileOutput)
runC tlm rewrites = runWriterT
. flip runReaderT (initCompileEnv tlm rewrites)
. flip evalStateT initCompileState
-- Main compile function
------------------------
compile :: Options -> ModuleEnv -> IsMain -> Definition ->
TCM (CompiledDef, CompileOutput)
compile opts tlm _ def = withCurrentModule (qnameModule $ defName def) $ runC tlm (optRewrites opts) $
compileAndTag <* postCompile
where
tag code = [(nameBindingSite $ qnameName $ defName def, code)]
single x = [x]
compileAndTag :: C CompiledDef
compileAndTag = processPragma (defName def) >>= \ p ->
setCurrentRangeQ (defName def) $ do
reportSDoc "agda2hs.compile" 5 $
text "Compiling definition: " <+> prettyTCM (defName def)
reportSDoc "agda2hs.compile" 45 $
text "Pragma: " <+> text (show p)
reportSDoc "agda2hs.compile" 45 $
text "Compiling definition: " <+> pretty (theDef def)
case (p , defInstance def , theDef def) of
(NoPragma, _, _) ->
return []
(ExistingClassPragma, _, _) ->
return [] -- No code generation, but affects how projections are compiled
(UnboxPragma s, _, defn) ->
checkUnboxPragma defn >> return [] -- also no code generation
(TransparentPragma , _, Function{}) ->
checkTransparentPragma def >> return [] -- also no code generation
(ClassPragma ms, _, Record{}) ->
tag . single <$> compileRecord (ToClass ms) def
(NewTypePragma ds, _, Record{}) ->
tag . single <$> compileRecord (ToRecordNewType ds) def
(NewTypePragma ds, _, Datatype{}) ->
tag <$> compileData ToDataNewType ds def
(DefaultPragma ds, _, Datatype{}) ->
tag <$> compileData ToData ds def
(DerivePragma s, Just _, _) ->
tag . single <$> compileInstance (ToDerivation s) def
(DefaultPragma _, Just _, Axiom{}) ->
tag . single <$> compileInstance (ToDerivation Nothing) def
(DefaultPragma _, Just _, _) ->
tag . single <$> compileInstance ToDefinition def
(DefaultPragma _, _, Axiom{}) ->
tag <$> compilePostulate def
(DefaultPragma _, _, Function{}) ->
tag <$> compileFun True def
(DefaultPragma ds, _, Record{}) ->
tag . single <$> compileRecord (ToRecord ds) def
_ ->
genericDocError =<< do
text "Don't know how to compile" <+> prettyTCM (defName def)
postCompile :: C ()
postCompile =
whenM ((> 0) . lcaseUsed <$> get) $
tellExtension Hs.LambdaCase