{-# OPTIONS -fno-warn-name-shadowing #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE MonoLocalBinds #-}
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 Fay.Compiler.Prelude
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.Monad.Identity
import Data.Generics.Traversable
import Data.Lens.Light
import GHC.Exts (Constraint)
import Language.Haskell.Exts
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 @Resolvable (\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