module Language.Haskell.Names.Open.Base
( Resolvable (..)
, intro
, mergeLocalScopes
, alg
, Scope (..)
, setWcNames
, gTable
, exprV
, exprT
, rmap
, wcNames
, nameCtx
, NameContext (..)
, initialScope
, binderV
, Alg (..)
, binderT
, defaultRtraverse
, lTable
) where
import Language.Haskell.Names.GetBound
import qualified Language.Haskell.Names.GlobalSymbolTable as Global
import qualified Language.Haskell.Names.LocalSymbolTable as Local
import Language.Haskell.Names.RecordWildcards
import Control.Applicative
import Control.Monad.Identity
import Data.Generics.Traversable
import Data.Lens.Light
import Data.List
import Data.Monoid
import Data.Typeable
import GHC.Exts (Constraint)
import Language.Haskell.Exts.Annotated
data NameContext
= BindingT
| BindingV
| ReferenceT
| ReferenceV
| Other
data Scope = Scope
{ _gTable :: Global.Table
, _lTable :: Local.Table
, _nameCtx :: NameContext
, _wcNames :: WcNames
}
makeLens ''Scope
initialScope :: Global.Table -> Scope
initialScope tbl = Scope tbl Local.empty Other []
mergeLocalScopes :: Scope -> Scope -> Scope
mergeLocalScopes sc1 sc2 =
modL lTable (<> sc2 ^. lTable) sc1
newtype Alg w = Alg
{ runAlg :: forall d . Resolvable d => d -> Scope -> w d }
alg :: (?alg :: Alg w, Resolvable d) => d -> Scope -> w d
alg = runAlg ?alg
data ConstraintProxy (p :: * -> Constraint) = ConstraintProxy
defaultRtraverse
:: (GTraversable Resolvable a, Applicative f, ?alg :: Alg f)
=> a -> Scope -> f a
defaultRtraverse a sc =
let ?c = ConstraintProxy :: ConstraintProxy Resolvable
in gtraverse (\a -> alg a sc) a
class Typeable a => Resolvable a where
rtraverse
:: (Applicative f, ?alg :: Alg f)
=> a -> Scope -> f a
instance (Typeable a, GTraversable Resolvable a) => Resolvable a where
rtraverse = defaultRtraverse
rmap
:: Resolvable a
=> (forall b. Resolvable b => Scope -> b -> b)
-> Scope -> a -> a
rmap f sc =
let ?alg = Alg $ \a sc -> Identity (f sc a)
in runIdentity . flip rtraverse sc
intro :: (SrcInfo l, GetBound a l) => a -> Scope -> Scope
intro node sc =
modL lTable
(\tbl -> foldl' (flip Local.addValue) tbl $
getBound (sc ^. gTable) node)
sc
setNameCtx :: NameContext -> Scope -> Scope
setNameCtx = setL nameCtx
setWcNames :: WcNames -> Scope -> Scope
setWcNames = setL wcNames
binderV :: Scope -> Scope
binderV = setNameCtx BindingV
binderT :: Scope -> Scope
binderT = setNameCtx BindingT
exprV :: Scope -> Scope
exprV = setNameCtx ReferenceV
exprT :: Scope -> Scope
exprT = setNameCtx ReferenceT