{-# OPTIONS -fno-warn-name-shadowing #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE TupleSections #-}
module Language.Haskell.Names.RecordWildcards
( patWcNames
, wcFieldName
, WcNames
, expWcNames
, wcFieldOrigName
) where
import qualified Language.Haskell.Names.GlobalSymbolTable as Global
import qualified Language.Haskell.Names.LocalSymbolTable as Local
import Language.Haskell.Names.SyntaxUtils
import Language.Haskell.Names.Types
import Control.Monad
import qualified Data.Map as Map
import Data.Maybe
import qualified Data.Set as Set
import Language.Haskell.Exts
type WcNames = [WcField]
data WcField = WcField
{ WcField -> Name ()
wcFieldName :: Name ()
, WcField -> OrigName
wcFieldOrigName :: OrigName
, WcField -> Bool
wcExistsGlobalValue :: Bool
}
getElidedFields
:: Global.Table
-> QName l
-> [Name l]
-> WcNames
getElidedFields :: Table -> QName l -> [Name l] -> WcNames
getElidedFields gt :: Table
gt con :: QName l
con fields :: [Name l]
fields =
let
givenFieldNames :: Map.Map (Name ()) ()
givenFieldNames :: Map (Name ()) ()
givenFieldNames =
[(Name (), ())] -> Map (Name ()) ()
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Name (), ())] -> Map (Name ()) ())
-> ([Name l] -> [(Name (), ())]) -> [Name l] -> Map (Name ()) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name l -> (Name (), ())) -> [Name l] -> [(Name (), ())]
forall a b. (a -> b) -> [a] -> [b]
map ((, ()) (Name () -> (Name (), ()))
-> (Name l -> Name ()) -> Name l -> (Name (), ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name l -> Name ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void) ([Name l] -> Map (Name ()) ()) -> [Name l] -> Map (Name ()) ()
forall a b. (a -> b) -> a -> b
$ [Name l]
fields
(mbConOrigName :: Maybe OrigName
mbConOrigName, mbTypeOrigName :: Maybe OrigName
mbTypeOrigName) =
case QName l -> Table -> Result l (SymValueInfo OrigName)
forall l. QName l -> Table -> Result l (SymValueInfo OrigName)
Global.lookupValue QName l
con Table
gt of
Global.Result info :: SymValueInfo OrigName
info@SymConstructor{} ->
(OrigName -> Maybe OrigName
forall a. a -> Maybe a
Just (OrigName -> Maybe OrigName) -> OrigName -> Maybe OrigName
forall a b. (a -> b) -> a -> b
$ SymValueInfo OrigName -> OrigName
forall name. SymValueInfo name -> name
sv_origName SymValueInfo OrigName
info, OrigName -> Maybe OrigName
forall a. a -> Maybe a
Just (OrigName -> Maybe OrigName) -> OrigName -> Maybe OrigName
forall a b. (a -> b) -> a -> b
$ SymValueInfo OrigName -> OrigName
forall name. SymValueInfo name -> name
sv_typeName SymValueInfo OrigName
info)
_ -> (Maybe OrigName
forall a. Maybe a
Nothing, Maybe OrigName
forall a. Maybe a
Nothing)
allValueInfos :: Set.Set (SymValueInfo OrigName)
allValueInfos :: Set (SymValueInfo OrigName)
allValueInfos = [Set (SymValueInfo OrigName)] -> Set (SymValueInfo OrigName)
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions ([Set (SymValueInfo OrigName)] -> Set (SymValueInfo OrigName))
-> [Set (SymValueInfo OrigName)] -> Set (SymValueInfo OrigName)
forall a b. (a -> b) -> a -> b
$ Map GName (Set (SymValueInfo OrigName))
-> [Set (SymValueInfo OrigName)]
forall k a. Map k a -> [a]
Map.elems (Map GName (Set (SymValueInfo OrigName))
-> [Set (SymValueInfo OrigName)])
-> Map GName (Set (SymValueInfo OrigName))
-> [Set (SymValueInfo OrigName)]
forall a b. (a -> b) -> a -> b
$ Table -> Map GName (Set (SymValueInfo OrigName))
Global.values Table
gt
ourFieldInfos :: Set.Set (SymValueInfo OrigName)
ourFieldInfos :: Set (SymValueInfo OrigName)
ourFieldInfos =
case Maybe OrigName
mbConOrigName of
Nothing -> Set (SymValueInfo OrigName)
forall a. Set a
Set.empty
Just conOrigName :: OrigName
conOrigName ->
((SymValueInfo OrigName -> Bool)
-> Set (SymValueInfo OrigName) -> Set (SymValueInfo OrigName))
-> Set (SymValueInfo OrigName)
-> (SymValueInfo OrigName -> Bool)
-> Set (SymValueInfo OrigName)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (SymValueInfo OrigName -> Bool)
-> Set (SymValueInfo OrigName) -> Set (SymValueInfo OrigName)
forall a. (a -> Bool) -> Set a -> Set a
Set.filter Set (SymValueInfo OrigName)
allValueInfos ((SymValueInfo OrigName -> Bool) -> Set (SymValueInfo OrigName))
-> (SymValueInfo OrigName -> Bool) -> Set (SymValueInfo OrigName)
forall a b. (a -> b) -> a -> b
$ \v :: SymValueInfo OrigName
v ->
case SymValueInfo OrigName
v of
SymSelector { [OrigName]
sv_constructors :: forall name. SymValueInfo name -> [name]
sv_constructors :: [OrigName]
sv_constructors }
| OrigName
conOrigName OrigName -> [OrigName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [OrigName]
sv_constructors -> Bool
True
_ -> Bool
False
existsGlobalValue :: Name () -> Bool
existsGlobalValue :: Name () -> Bool
existsGlobalValue name :: Name ()
name =
case QName () -> Table -> Result () (SymValueInfo OrigName)
forall l. QName l -> Table -> Result l (SymValueInfo OrigName)
Global.lookupValue (() -> Name () -> QName ()
forall l. l -> Name l -> QName l
UnQual () Name ()
name) Table
gt of
Global.Result info :: SymValueInfo OrigName
info
| Just typeOrigName :: OrigName
typeOrigName <- Maybe OrigName
mbTypeOrigName
, SymSelector {} <- SymValueInfo OrigName
info
, SymValueInfo OrigName -> OrigName
forall name. SymValueInfo name -> name
sv_typeName SymValueInfo OrigName
info OrigName -> OrigName -> Bool
forall a. Eq a => a -> a -> Bool
== OrigName
typeOrigName
-> Bool
False
| Bool
otherwise -> Bool
True
_ -> Bool
False
ourFieldNames :: Map.Map (Name ()) WcField
ourFieldNames :: Map (Name ()) WcField
ourFieldNames =
[(Name (), WcField)] -> Map (Name ()) WcField
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Name (), WcField)] -> Map (Name ()) WcField)
-> [(Name (), WcField)] -> Map (Name ()) WcField
forall a b. (a -> b) -> a -> b
$
(SymValueInfo OrigName -> (Name (), WcField))
-> [SymValueInfo OrigName] -> [(Name (), WcField)]
forall a b. (a -> b) -> [a] -> [b]
map
(
(\orig :: OrigName
orig ->
let name :: Name ()
name = String -> Name ()
stringToName (String -> Name ()) -> (OrigName -> String) -> OrigName -> Name ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GName -> String
gName (GName -> String) -> (OrigName -> GName) -> OrigName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OrigName -> GName
origGName (OrigName -> Name ()) -> OrigName -> Name ()
forall a b. (a -> b) -> a -> b
$ OrigName
orig in
(Name ()
name, ) (WcField -> (Name (), WcField)) -> WcField -> (Name (), WcField)
forall a b. (a -> b) -> a -> b
$
WcField :: Name () -> OrigName -> Bool -> WcField
WcField
{ wcFieldName :: Name ()
wcFieldName = Name ()
name
, wcFieldOrigName :: OrigName
wcFieldOrigName = OrigName
orig
, wcExistsGlobalValue :: Bool
wcExistsGlobalValue = Name () -> Bool
existsGlobalValue Name ()
name
}
) (OrigName -> (Name (), WcField))
-> (SymValueInfo OrigName -> OrigName)
-> SymValueInfo OrigName
-> (Name (), WcField)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymValueInfo OrigName -> OrigName
forall name. SymValueInfo name -> name
sv_origName
)
([SymValueInfo OrigName] -> [(Name (), WcField)])
-> [SymValueInfo OrigName] -> [(Name (), WcField)]
forall a b. (a -> b) -> a -> b
$ Set (SymValueInfo OrigName) -> [SymValueInfo OrigName]
forall a. Set a -> [a]
Set.toList Set (SymValueInfo OrigName)
ourFieldInfos
in Map (Name ()) WcField -> WcNames
forall k a. Map k a -> [a]
Map.elems (Map (Name ()) WcField -> WcNames)
-> Map (Name ()) WcField -> WcNames
forall a b. (a -> b) -> a -> b
$ Map (Name ()) WcField
ourFieldNames Map (Name ()) WcField -> Map (Name ()) () -> Map (Name ()) WcField
forall k a b. Ord k => Map k a -> Map k b -> Map k a
`Map.difference` Map (Name ()) ()
givenFieldNames
nameOfPatField :: PatField l -> Maybe (Name l)
nameOfPatField :: PatField l -> Maybe (Name l)
nameOfPatField pf :: PatField l
pf =
case PatField l
pf of
PFieldPat _ qn :: QName l
qn _ -> Name l -> Maybe (Name l)
forall a. a -> Maybe a
Just (Name l -> Maybe (Name l)) -> Name l -> Maybe (Name l)
forall a b. (a -> b) -> a -> b
$ QName l -> Name l
forall l. QName l -> Name l
qNameToName QName l
qn
PFieldPun _ qn :: QName l
qn -> Name l -> Maybe (Name l)
forall a. a -> Maybe a
Just (Name l -> Maybe (Name l)) -> Name l -> Maybe (Name l)
forall a b. (a -> b) -> a -> b
$ QName l -> Name l
forall l. QName l -> Name l
qNameToName QName l
qn
PFieldWildcard {} -> Maybe (Name l)
forall a. Maybe a
Nothing
nameOfUpdField :: FieldUpdate l -> Maybe (Name l)
nameOfUpdField :: FieldUpdate l -> Maybe (Name l)
nameOfUpdField pf :: FieldUpdate l
pf =
case FieldUpdate l
pf of
FieldUpdate _ qn :: QName l
qn _ -> Name l -> Maybe (Name l)
forall a. a -> Maybe a
Just (Name l -> Maybe (Name l)) -> Name l -> Maybe (Name l)
forall a b. (a -> b) -> a -> b
$ QName l -> Name l
forall l. QName l -> Name l
qNameToName QName l
qn
FieldPun _ qn :: QName l
qn -> Name l -> Maybe (Name l)
forall a. a -> Maybe a
Just (Name l -> Maybe (Name l)) -> Name l -> Maybe (Name l)
forall a b. (a -> b) -> a -> b
$ QName l -> Name l
forall l. QName l -> Name l
qNameToName QName l
qn
FieldWildcard {} -> Maybe (Name l)
forall a. Maybe a
Nothing
patWcNames
:: Global.Table
-> QName l
-> [PatField l]
-> WcNames
patWcNames :: Table -> QName l -> [PatField l] -> WcNames
patWcNames gt :: Table
gt con :: QName l
con patfs :: [PatField l]
patfs =
Table -> QName l -> [Name l] -> WcNames
forall l. Table -> QName l -> [Name l] -> WcNames
getElidedFields Table
gt QName l
con ([Name l] -> WcNames) -> [Name l] -> WcNames
forall a b. (a -> b) -> a -> b
$
(PatField l -> Maybe (Name l)) -> [PatField l] -> [Name l]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe PatField l -> Maybe (Name l)
forall l. PatField l -> Maybe (Name l)
nameOfPatField [PatField l]
patfs
expWcNames
:: Global.Table
-> Local.Table
-> QName l
-> [FieldUpdate l]
-> WcNames
expWcNames :: Table -> Table -> QName l -> [FieldUpdate l] -> WcNames
expWcNames gt :: Table
gt lt :: Table
lt con :: QName l
con patfs :: [FieldUpdate l]
patfs =
(WcField -> Bool) -> WcNames -> WcNames
forall a. (a -> Bool) -> [a] -> [a]
filter WcField -> Bool
isInScope (WcNames -> WcNames) -> WcNames -> WcNames
forall a b. (a -> b) -> a -> b
$
Table -> QName l -> [Name l] -> WcNames
forall l. Table -> QName l -> [Name l] -> WcNames
getElidedFields Table
gt QName l
con ([Name l] -> WcNames) -> [Name l] -> WcNames
forall a b. (a -> b) -> a -> b
$
(FieldUpdate l -> Maybe (Name l)) -> [FieldUpdate l] -> [Name l]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe FieldUpdate l -> Maybe (Name l)
forall l. FieldUpdate l -> Maybe (Name l)
nameOfUpdField [FieldUpdate l]
patfs
where
isInScope :: WcField -> Bool
isInScope field :: WcField
field
| Right {} <- QName () -> Table -> Either (Error ()) SrcLoc
forall l. QName l -> Table -> Either (Error l) SrcLoc
Local.lookupValue QName ()
qn Table
lt = Bool
True
| Bool
otherwise = WcField -> Bool
wcExistsGlobalValue WcField
field
where
qn :: QName ()
qn = () -> Name () -> QName ()
forall l. l -> Name l -> QName l
UnQual () (Name () -> QName ()) -> Name () -> QName ()
forall a b. (a -> b) -> a -> b
$ WcField -> Name ()
wcFieldName WcField
field