{-# LANGUAGE NamedFieldPuns #-} -- | Pure functions for working with CompileState module Fay.Compiler.State where import Fay.Compiler.Misc import Fay.Compiler.QName import qualified Fay.Exts.NoAnnotation as N import Fay.Types import qualified Data.Map as M import Data.Set (Set) import qualified Data.Set as S import Language.Haskell.Names (sv_origName, Symbols (Symbols), SymValueInfo (SymValue, SymMethod, SymSelector, SymConstructor), OrigName, sv_typeName) -- | Get all non local identifiers that should be exported in the JS module scope. getNonLocalExportsWithoutNewtypes :: N.ModuleName -> CompileState -> Maybe (Set N.QName) getNonLocalExportsWithoutNewtypes modName cs = fmap ( S.filter (not . isLocal) . S.map (origName2QName . sv_origName) . S.filter (not . (`isNewtype` cs)) . (\(Symbols exports _) -> exports) ) . M.lookup modName . stateInterfaces $ cs where isLocal = (Just modName ==) . qModName getLocalExportsWithoutNewtypes :: N.ModuleName -> CompileState -> Maybe (Set N.QName) getLocalExportsWithoutNewtypes modName cs = fmap ( S.filter isLocal . S.map (origName2QName . sv_origName) . S.filter (not . (`isNewtype` cs)) . (\(Symbols exports _) -> exports) ) . M.lookup modName . stateInterfaces $ cs where isLocal = (Just modName ==) . qModName -- | Is this *resolved* name a new type constructor or destructor? isNewtype :: SymValueInfo OrigName -> CompileState -> Bool isNewtype s cs = case s of SymValue{} -> False SymMethod{} -> False SymSelector { sv_typeName = tn } -> not . (`isNewtypeDest` cs) . origName2QName $ tn SymConstructor { sv_typeName = tn } -> not . (`isNewtypeCons` cs) . origName2QName $ tn -- | Is this *resolved* name a new type destructor? isNewtypeDest :: N.QName -> CompileState -> Bool isNewtypeDest o = any (\(_,mdest,_) -> mdest == Just o) . stateNewtypes -- | Is this *resolved* name a new type constructor? isNewtypeCons :: N.QName -> CompileState -> Bool isNewtypeCons o = any (\(cons,_,_) -> cons == o) . stateNewtypes -- | Add a ModulePath to CompileState, meaning it has been printed. addModulePath :: ModulePath -> CompileState -> CompileState addModulePath mp cs = cs { stateJsModulePaths = mp `S.insert` stateJsModulePaths cs } -- | Has this ModulePath been added/printed? addedModulePath :: ModulePath -> CompileState -> Bool addedModulePath mp CompileState { stateJsModulePaths } = mp `S.member` stateJsModulePaths -- | Find the type signature of a top level name findTypeSig :: N.QName -> CompileState -> Maybe N.Type findTypeSig n = M.lookup n . stateTypeSigs