{-# OPTIONS_GHC -Wunused-imports #-}
module Agda.Syntax.Scope.Flat
( FlatScope
, flattenScope
, getDefinedNames
, localNames
) where
import Data.Bifunctor
import Data.Either (partitionEithers)
import qualified Data.List as List
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Agda.Syntax.Abstract.Name as A
import Agda.Syntax.Concrete
import Agda.Syntax.Notation
import Agda.Syntax.Scope.Base
import Agda.Syntax.Scope.Monad
import Agda.TypeChecking.Monad.Debug
import Agda.Utils.Impossible
import Agda.Utils.Lens
import Agda.Utils.List
import Agda.Utils.List1 (List1)
import qualified Agda.Utils.List1 as List1
import Agda.Utils.Maybe
import Agda.Syntax.Common.Pretty
newtype FlatScope = Flat (Map QName (List1 AbstractName))
deriving Int -> FlatScope -> Doc
[FlatScope] -> Doc
FlatScope -> Doc
(FlatScope -> Doc)
-> (Int -> FlatScope -> Doc)
-> ([FlatScope] -> Doc)
-> Pretty FlatScope
forall a.
(a -> Doc) -> (Int -> a -> Doc) -> ([a] -> Doc) -> Pretty a
$cpretty :: FlatScope -> Doc
pretty :: FlatScope -> Doc
$cprettyPrec :: Int -> FlatScope -> Doc
prettyPrec :: Int -> FlatScope -> Doc
$cprettyList :: [FlatScope] -> Doc
prettyList :: [FlatScope] -> Doc
Pretty
flattenScope :: [[Name]] -> ScopeInfo -> FlatScope
flattenScope :: [[Name]] -> ScopeInfo -> FlatScope
flattenScope [[Name]]
ms ScopeInfo
scope =
Map QName (List1 AbstractName) -> FlatScope
Flat (Map QName (List1 AbstractName) -> FlatScope)
-> Map QName (List1 AbstractName) -> FlatScope
forall a b. (a -> b) -> a -> b
$
(List1 AbstractName -> List1 AbstractName -> List1 AbstractName)
-> Map QName (List1 AbstractName)
-> Map QName (List1 AbstractName)
-> Map QName (List1 AbstractName)
forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith List1 AbstractName -> List1 AbstractName -> List1 AbstractName
forall a. Semigroup a => a -> a -> a
(<>)
([[Name]]
-> (forall a. InScope a => Scope -> ThingsInScope a)
-> Scope
-> Map QName (List1 AbstractName)
build [[Name]]
ms Scope -> ThingsInScope a
forall a. InScope a => Scope -> ThingsInScope a
allNamesInScope Scope
root)
Map QName (List1 AbstractName)
imported
where
current :: Scope
current = ModuleName -> Scope
moduleScope (ModuleName -> Scope) -> ModuleName -> Scope
forall a b. (a -> b) -> a -> b
$ ScopeInfo
scope ScopeInfo -> Lens' ScopeInfo ModuleName -> ModuleName
forall o i. o -> Lens' o i -> i
^. (ModuleName -> f ModuleName) -> ScopeInfo -> f ScopeInfo
Lens' ScopeInfo ModuleName
scopeCurrent
root :: Scope
root = [Scope] -> Scope
mergeScopes ([Scope] -> Scope) -> [Scope] -> Scope
forall a b. (a -> b) -> a -> b
$ Scope
current Scope -> [Scope] -> [Scope]
forall a. a -> [a] -> [a]
: (ModuleName -> Scope) -> [ModuleName] -> [Scope]
forall a b. (a -> b) -> [a] -> [b]
map ModuleName -> Scope
moduleScope (Scope -> [ModuleName]
scopeParents Scope
current)
imported :: Map QName (List1 AbstractName)
imported = (List1 AbstractName -> List1 AbstractName -> List1 AbstractName)
-> [Map QName (List1 AbstractName)]
-> Map QName (List1 AbstractName)
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
Map.unionsWith List1 AbstractName -> List1 AbstractName -> List1 AbstractName
forall a. Semigroup a => a -> a -> a
(<>)
[ QName
-> Map QName (List1 AbstractName) -> Map QName (List1 AbstractName)
forall {a}. QName -> Map QName a -> Map QName a
qual QName
c ([[Name]]
-> (forall a. InScope a => Scope -> ThingsInScope a)
-> Scope
-> Map QName (List1 AbstractName)
build [[Name]]
ms' Scope -> ThingsInScope a
forall a. InScope a => Scope -> ThingsInScope a
exportedNamesInScope (Scope -> Map QName (List1 AbstractName))
-> Scope -> Map QName (List1 AbstractName)
forall a b. (a -> b) -> a -> b
$ ModuleName -> Scope
moduleScope ModuleName
a)
| (QName
c, ModuleName
a) <- Map QName ModuleName -> [(QName, ModuleName)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map QName ModuleName -> [(QName, ModuleName)])
-> Map QName ModuleName -> [(QName, ModuleName)]
forall a b. (a -> b) -> a -> b
$ Scope -> Map QName ModuleName
scopeImports Scope
root
, let
ms' :: [[Name]]
ms' = ([Name] -> Maybe [Name]) -> [[Name]] -> [[Name]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([Name] -> [Name] -> Maybe [Name]
forall a. Eq a => [a] -> [a] -> Maybe [a]
List.stripPrefix ([Name] -> [Name] -> Maybe [Name])
-> [Name] -> [Name] -> Maybe [Name]
forall a b. (a -> b) -> a -> b
$ List1 Name -> [Item (List1 Name)]
forall l. IsList l => l -> [Item l]
List1.toList (List1 Name -> [Item (List1 Name)])
-> List1 Name -> [Item (List1 Name)]
forall a b. (a -> b) -> a -> b
$ QName -> List1 Name
qnameParts QName
c) [[Name]]
ms
, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [[Name]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Name]]
ms' ]
qual :: QName -> Map QName a -> Map QName a
qual QName
c = (QName -> QName) -> Map QName a -> Map QName a
forall k1 k2 a. (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeysMonotonic (QName -> QName -> QName
q QName
c)
where
q :: QName -> QName -> QName
q (QName Name
x) = Name -> QName -> QName
Qual Name
x
q (Qual Name
m QName
x) = Name -> QName -> QName
Qual Name
m (QName -> QName) -> (QName -> QName) -> QName -> QName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QName -> QName -> QName
q QName
x
build :: [[Name]] -> (forall a. InScope a => Scope -> ThingsInScope a) -> Scope -> Map QName (List1 AbstractName)
build :: [[Name]]
-> (forall a. InScope a => Scope -> ThingsInScope a)
-> Scope
-> Map QName (List1 AbstractName)
build [[Name]]
ms forall a. InScope a => Scope -> ThingsInScope a
getNames Scope
s = (List1 AbstractName -> List1 AbstractName -> List1 AbstractName)
-> [Map QName (List1 AbstractName)]
-> Map QName (List1 AbstractName)
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
Map.unionsWith List1 AbstractName -> List1 AbstractName -> List1 AbstractName
forall a. Semigroup a => a -> a -> a
(<>) ([Map QName (List1 AbstractName)]
-> Map QName (List1 AbstractName))
-> [Map QName (List1 AbstractName)]
-> Map QName (List1 AbstractName)
forall a b. (a -> b) -> a -> b
$
(Name -> QName)
-> Map Name (List1 AbstractName) -> Map QName (List1 AbstractName)
forall k1 k2 a. (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeysMonotonic Name -> QName
QName (Scope -> Map Name (List1 AbstractName)
forall a. InScope a => Scope -> ThingsInScope a
getNames Scope
s) Map QName (List1 AbstractName)
-> [Map QName (List1 AbstractName)]
-> [Map QName (List1 AbstractName)]
forall a. a -> [a] -> [a]
:
[ (QName -> QName)
-> Map QName (List1 AbstractName) -> Map QName (List1 AbstractName)
forall k1 k2 a. (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeysMonotonic (\ QName
y -> Name -> QName -> QName
Qual Name
x QName
y) (Map QName (List1 AbstractName) -> Map QName (List1 AbstractName))
-> Map QName (List1 AbstractName) -> Map QName (List1 AbstractName)
forall a b. (a -> b) -> a -> b
$
[[Name]]
-> (forall a. InScope a => Scope -> ThingsInScope a)
-> Scope
-> Map QName (List1 AbstractName)
build [[Name]]
ms' Scope -> ThingsInScope a
forall a. InScope a => Scope -> ThingsInScope a
exportedNamesInScope (Scope -> Map QName (List1 AbstractName))
-> Scope -> Map QName (List1 AbstractName)
forall a b. (a -> b) -> a -> b
$ ModuleName -> Scope
moduleScope ModuleName
m
| (Name
x, List1 AbstractModule
mods) <- Map Name (List1 AbstractModule) -> [(Name, List1 AbstractModule)]
forall k a. Map k a -> [(k, a)]
Map.toList (Scope -> Map Name (List1 AbstractModule)
forall a. InScope a => Scope -> ThingsInScope a
getNames Scope
s)
, let ms' :: [[Name]]
ms' = [ [Name]
tl | Name
hd:[Name]
tl <- [[Name]]
ms, Name
hd Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
x ]
, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [[Name]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Name]]
ms'
, AbsModule ModuleName
m WhyInScope
_ <- List1 AbstractModule -> [Item (List1 AbstractModule)]
forall l. IsList l => l -> [Item l]
List1.toList List1 AbstractModule
mods
]
moduleScope :: A.ModuleName -> Scope
moduleScope :: ModuleName -> Scope
moduleScope ModuleName
m = Scope -> Maybe Scope -> Scope
forall a. a -> Maybe a -> a
fromMaybe Scope
forall a. HasCallStack => a
__IMPOSSIBLE__ (Maybe Scope -> Scope) -> Maybe Scope -> Scope
forall a b. (a -> b) -> a -> b
$ ModuleName -> Map ModuleName Scope -> Maybe Scope
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup ModuleName
m (Map ModuleName Scope -> Maybe Scope)
-> Map ModuleName Scope -> Maybe Scope
forall a b. (a -> b) -> a -> b
$ ScopeInfo
scope ScopeInfo
-> Lens' ScopeInfo (Map ModuleName Scope) -> Map ModuleName Scope
forall o i. o -> Lens' o i -> i
^. (Map ModuleName Scope -> f (Map ModuleName Scope))
-> ScopeInfo -> f ScopeInfo
Lens' ScopeInfo (Map ModuleName Scope)
scopeModules
getDefinedNames :: KindsOfNames -> FlatScope -> [List1 NewNotation]
getDefinedNames :: KindsOfNames -> FlatScope -> [List1 NewNotation]
getDefinedNames KindsOfNames
kinds (Flat Map QName (List1 AbstractName)
names) =
[ List1 NewNotation -> List1 NewNotation
mergeNotations (List1 NewNotation -> List1 NewNotation)
-> List1 NewNotation -> List1 NewNotation
forall a b. (a -> b) -> a -> b
$ (AbstractName -> NewNotation)
-> List1 AbstractName -> List1 NewNotation
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (QName -> Name -> NewNotation
namesToNotation QName
x (Name -> NewNotation)
-> (AbstractName -> Name) -> AbstractName -> NewNotation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QName -> Name
A.qnameName (QName -> Name) -> (AbstractName -> QName) -> AbstractName -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractName -> QName
anameName) List1 AbstractName
ds
| (QName
x, List1 AbstractName
ds) <- Map QName (List1 AbstractName) -> [(QName, List1 AbstractName)]
forall k a. Map k a -> [(k, a)]
Map.toList Map QName (List1 AbstractName)
names
, (AbstractName -> Bool) -> List1 AbstractName -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((KindOfName -> KindsOfNames -> Bool
`elemKindsOfNames` KindsOfNames
kinds) (KindOfName -> Bool)
-> (AbstractName -> KindOfName) -> AbstractName -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractName -> KindOfName
anameKind) List1 AbstractName
ds
]
localNames :: FlatScope -> ScopeM ([QName], [NewNotation])
localNames :: FlatScope -> ScopeM ([QName], [NewNotation])
localNames FlatScope
flat = do
let defs :: [List1 NewNotation]
defs = KindsOfNames -> FlatScope -> [List1 NewNotation]
getDefinedNames KindsOfNames
allKindsOfNames FlatScope
flat
locals <- ((Name, Name) -> Name) -> [(Name, Name)] -> [(Name, Name)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
nubOn (Name, Name) -> Name
forall a b. (a, b) -> a
fst ([(Name, Name)] -> [(Name, Name)])
-> (LocalVars -> [(Name, Name)]) -> LocalVars -> [(Name, Name)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalVars -> [(Name, Name)]
notShadowedLocals (LocalVars -> [(Name, Name)])
-> TCMT IO LocalVars -> TCMT IO [(Name, Name)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO LocalVars
forall (m :: * -> *). ReadTCState m => m LocalVars
getLocalVars
reportS "scope.operators" 50
[ "flat = " ++ prettyShow flat
, "defs = " ++ prettyShow defs
, "locals= " ++ prettyShow locals
]
let localNots = ((Name, Name) -> NewNotation) -> [(Name, Name)] -> [NewNotation]
forall a b. (a -> b) -> [a] -> [b]
map (Name, Name) -> NewNotation
localOp [(Name, Name)]
locals
notLocal = Bool -> Bool
not (Bool -> Bool) -> (NewNotation -> Bool) -> NewNotation -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [QName] -> QName -> Bool
forall a. Ord a => [a] -> a -> Bool
hasElem ((NewNotation -> QName) -> [NewNotation] -> [QName]
forall a b. (a -> b) -> [a] -> [b]
map NewNotation -> QName
notaName [NewNotation]
localNots) (QName -> Bool) -> (NewNotation -> QName) -> NewNotation -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NewNotation -> QName
notaName
otherNots = (List1 NewNotation -> [NewNotation])
-> [List1 NewNotation] -> [NewNotation]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((NewNotation -> Bool) -> List1 NewNotation -> [NewNotation]
forall a. (a -> Bool) -> NonEmpty a -> [a]
List1.filter NewNotation -> Bool
notLocal) [List1 NewNotation]
defs
return $ second (map useDefaultFixity) $ split $ localNots ++ otherNots
where
localOp :: (Name, Name) -> NewNotation
localOp (Name
x, Name
y) = QName -> Name -> NewNotation
namesToNotation (Name -> QName
QName Name
x) Name
y
split :: [NewNotation] -> ([QName], [NewNotation])
split = [Either QName NewNotation] -> ([QName], [NewNotation])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ([Either QName NewNotation] -> ([QName], [NewNotation]))
-> ([NewNotation] -> [Either QName NewNotation])
-> [NewNotation]
-> ([QName], [NewNotation])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NewNotation -> [Either QName NewNotation])
-> [NewNotation] -> [Either QName NewNotation]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap NewNotation -> [Either QName NewNotation]
opOrNot
opOrNot :: NewNotation -> [Either QName NewNotation]
opOrNot NewNotation
n = QName -> Either QName NewNotation
forall a b. a -> Either a b
Left (NewNotation -> QName
notaName NewNotation
n) Either QName NewNotation
-> [Either QName NewNotation] -> [Either QName NewNotation]
forall a. a -> [a] -> [a]
:
[NewNotation -> Either QName NewNotation
forall a b. b -> Either a b
Right NewNotation
n | Bool -> Bool
not ([NotationPart] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (NewNotation -> [NotationPart]
notation NewNotation
n))]