module Language.Haskell.Names.Annotated
( Scoped(..)
, NameInfo(..)
, annotateDecl
) where
import Language.Haskell.Names.Types
import Language.Haskell.Names.RecordWildcards
import Language.Haskell.Names.Open.Base
import Language.Haskell.Names.Open.Instances ()
import qualified Language.Haskell.Names.GlobalSymbolTable as Global
import qualified Language.Haskell.Names.LocalSymbolTable as Local
import Language.Haskell.Names.SyntaxUtils (annName,setAnn)
import Language.Haskell.Exts.Annotated.Simplify (sQName)
import Language.Haskell.Exts.Annotated
import qualified Language.Haskell.Exts.Syntax as UnAnn
import Data.Proxy
import Data.Lens.Light
import Data.Typeable (
Typeable, (:~:)(Refl), eqT)
import Control.Applicative
annotateDecl
:: forall a l .
(Resolvable (a (Scoped l)), Functor a, Typeable l)
=> Scope -> a l -> a (Scoped l)
annotateDecl sc = annotateRec (Proxy :: Proxy l) sc . fmap (Scoped None)
annotateRec
:: forall a l .
(Typeable l, Resolvable a)
=> Proxy l -> Scope -> a -> a
annotateRec _ sc a = go sc a where
go :: forall a . Resolvable a => Scope -> a -> a
go sc a
| ReferenceV <- getL nameCtx sc
, Just (Refl :: QName (Scoped l) :~: a) <- eqT
= lookupValue (fmap sLoc a) sc <$ a
| ReferenceT <- getL nameCtx sc
, Just (Refl :: QName (Scoped l) :~: a) <- eqT
= lookupType (fmap sLoc a) sc <$ a
| ReferenceUV <- getL nameCtx sc
, Just (Refl :: Name (Scoped l) :~: a) <- eqT
= lookupMethod (fmap sLoc a) sc <$ a
| ReferenceUT <- getL nameCtx sc
, Just (Refl :: QName (Scoped l) :~: a) <- eqT
= lookupAssociatedType (fmap sLoc a) sc <$ a
| BindingV <- getL nameCtx sc
, Just (Refl :: Name (Scoped l) :~: a) <- eqT
= Scoped ValueBinder (sLoc . ann $ a) <$ a
| BindingT <- getL nameCtx sc
, Just (Refl :: Name (Scoped l) :~: a) <- eqT
= Scoped TypeBinder (sLoc . ann $ a) <$ a
| Just (Refl :: FieldUpdate (Scoped l) :~: a) <- eqT
= case a of
FieldPun l n -> FieldPun l (lookupValue (sLoc <$> n) sc <$ n)
FieldWildcard l -> FieldWildcard (Scoped (RecExpWildcard namesRes) (sLoc l)) where
namesRes = do
f <- sc ^. wcNames
let qn = setAnn (sLoc l) (UnQual () (annName (wcFieldName f)))
case lookupValue qn sc of
Scoped info@(GlobalSymbol _ _) _ -> return (wcFieldName f,info)
Scoped info@(LocalValue _) _ -> return (wcFieldName f,info)
_ -> []
_ -> rmap go sc a
| Just (Refl :: PatField (Scoped l) :~: a) <- eqT
, PFieldWildcard l <- a
= let
namesRes = do
f <- sc ^. wcNames
let qn = UnQual () (annName (wcFieldName f))
Scoped (GlobalSymbol symbol _) _ <- return (lookupValue qn sc)
return (symbol {symbolModule = wcFieldModuleName f})
in PFieldWildcard (Scoped (RecPatWildcard namesRes) (sLoc l))
| otherwise
= rmap go sc a
lookupValue :: QName l -> Scope -> Scoped l
lookupValue (Special l _) _ = Scoped None l
lookupValue qn sc = Scoped nameInfo (ann qn)
where
nameInfo =
case Local.lookupValue qn $ getL lTable sc of
Right r -> LocalValue r
_ ->
case Global.lookupValue qn $ getL gTable sc of
Global.SymbolFound r -> GlobalSymbol r (sQName qn)
Global.Error e -> ScopeError e
Global.Special -> None
lookupType :: QName l -> Scope -> Scoped l
lookupType (Special l _) _ = Scoped None l
lookupType qn sc = Scoped nameInfo (ann qn)
where
nameInfo =
case Global.lookupType qn $ getL gTable sc of
Global.SymbolFound r -> GlobalSymbol r (sQName qn)
Global.Error e -> ScopeError e
Global.Special -> None
lookupMethod :: Name l -> Scope -> Scoped l
lookupMethod n sc = Scoped nameInfo (ann qn)
where
nameInfo =
case Global.lookupMethodOrAssociate qn $ getL gTable sc of
Global.SymbolFound r -> GlobalSymbol r (sQName qn)
Global.Error e -> ScopeError e
Global.Special -> None
qn = qualifyName (getL instQual sc) n
lookupAssociatedType :: QName l -> Scope -> Scoped l
lookupAssociatedType qn sc = Scoped nameInfo (ann qn)
where
nameInfo =
case Global.lookupMethodOrAssociate qn' $ getL gTable sc of
Global.SymbolFound r -> GlobalSymbol r (sQName qn)
Global.Error e -> ScopeError e
Global.Special -> None
qn' = case qn of
UnQual _ n -> qualifyName (getL instQual sc) n
_ -> qn
qualifyName :: Maybe UnAnn.ModuleName -> Name l -> QName l
qualifyName Nothing n = UnQual (ann n) n
qualifyName (Just (UnAnn.ModuleName moduleName)) n = Qual (ann n) annotatedModuleName n
where
annotatedModuleName = ModuleName (ann n) moduleName