module CompilerEnv where
import qualified Data.Map as Map (Map, keys, toList)
import Curry.Base.Ident (ModuleIdent, moduleName)
import Curry.Base.Pretty
import Curry.Base.Span (Span)
import Curry.Syntax
import Base.TopEnv (allBindings, allLocalBindings)
import Env.Class
import Env.Instance
import Env.Interface
import Env.ModuleAlias (AliasEnv, initAliasEnv)
import Env.OpPrec
import Env.TypeConstructor
import Env.Value
type CompEnv a = (CompilerEnv, a)
data CompilerEnv = CompilerEnv
{ moduleIdent :: ModuleIdent
, filePath :: FilePath
, extensions :: [KnownExtension]
, tokens :: [(Span, Token)]
, interfaceEnv :: InterfaceEnv
, aliasEnv :: AliasEnv
, tyConsEnv :: TCEnv
, classEnv :: ClassEnv
, instEnv :: InstEnv
, valueEnv :: ValueEnv
, opPrecEnv :: OpPrecEnv
}
initCompilerEnv :: ModuleIdent -> CompilerEnv
initCompilerEnv mid = CompilerEnv
{ moduleIdent = mid
, filePath = []
, extensions = []
, tokens = []
, interfaceEnv = initInterfaceEnv
, aliasEnv = initAliasEnv
, tyConsEnv = initTCEnv
, classEnv = initClassEnv
, instEnv = initInstEnv
, valueEnv = initDCEnv
, opPrecEnv = initOpPrecEnv
}
showCompilerEnv :: CompilerEnv -> Bool -> Bool -> String
showCompilerEnv env allBinds simpleEnv = show $ vcat
[ header "Module Identifier " $ text $ moduleName $ moduleIdent env
, header "FilePath" $ text $ filePath env
, header "Language Extensions" $ text $ show $ extensions env
, header "Interfaces " $ hcat $ punctuate comma
$ map (text . moduleName)
$ Map.keys $ interfaceEnv env
, header "Module Aliases " $ ppMap simpleEnv $ aliasEnv env
, header "Precedences " $ ppAL simpleEnv $ bindings $ opPrecEnv env
, header "Type Constructors " $ ppAL simpleEnv $ bindings $ tyConsEnv env
, header "Classes " $ ppMap simpleEnv $ classEnv env
, header "Instances " $ ppMap simpleEnv $ instEnv env
, header "Values " $ ppAL simpleEnv $ bindings $ valueEnv env
]
where
header hdr content = hang (text hdr <+> colon) 4 content
bindings = if allBinds then allBindings else allLocalBindings
ppMap :: (Show a, Pretty a, Show b, Pretty b) => Bool-> Map.Map a b -> Doc
ppMap True = ppMapPretty
ppMap False = ppMapShow
ppMapShow :: (Show a, Show b) => Map.Map a b -> Doc
ppMapShow = ppALShow . Map.toList
ppMapPretty :: (Pretty a, Pretty b) => Map.Map a b -> Doc
ppMapPretty = ppALPretty . Map.toList
ppAL :: (Show a, Pretty a, Show b, Pretty b) => Bool -> [(a, b)] -> Doc
ppAL True = ppALPretty
ppAL False = ppALShow
ppALShow :: (Show a, Show b) => [(a, b)] -> Doc
ppALShow xs = vcat
$ map (\(a,b) -> text (pad a keyWidth) <+> equals <+> text b) showXs
where showXs = map (\(a,b) -> (show a, show b)) xs
keyWidth = maximum (0 : map (length .fst) showXs)
pad s n = take n (s ++ repeat ' ')
ppALPretty :: (Pretty a, Pretty b) => [(a, b)] -> Doc
ppALPretty xs = vcat
$ map (\(a,b) -> text (pad a keyWidth) <+> equals <+> text b) showXs
where showXs = map (\(a,b) -> (render (pPrint a), render (pPrint b))) xs
keyWidth = maximum (0 : map (length .fst) showXs)
pad s n = take n (s ++ repeat ' ')