1
1
mirror of https://github.com/github/semantic.git synced 2024-12-29 18:06:14 +03:00

Remove Data.Abstract.Environment

This commit is contained in:
joshvera 2018-12-05 10:20:35 -05:00
parent 9fee3d5965
commit 073dca372d
3 changed files with 0 additions and 188 deletions

View File

@ -1,185 +0,0 @@
{-# LANGUAGE DeriveAnyClass, DerivingStrategies, GADTs #-}
module Data.Abstract.Environment
( Environment(..)
, Bindings(..)
, EvalContext(..)
, EnvironmentError(..)
, addresses
, aliasBindings
, allNames
, delete
, flatPairs
, head
, insert
, insertEnv
, intersect
, lookup
, lookupEnv'
, names
, newEnv
, overwrite
, pairs
, pop
, push
, roots
, unpairs
) where
import Data.Abstract.Live
import Data.Abstract.Name
import qualified Data.Set as Set
import qualified Data.Map as Map
import Prelude hiding (head, lookup)
import Prologue
-- | A map of names to values. Represents a single scope level of an environment chain.
newtype Bindings address = Bindings { unBindings :: Map.Map Name address }
deriving stock (Eq, Ord, Generic)
deriving anyclass (NFData)
instance Semigroup (Bindings address) where
(<>) (Bindings a) (Bindings b) = Bindings (a <> b)
instance Monoid (Bindings address) where
mempty = Bindings mempty
mappend = (<>)
instance Lower (Bindings address) where
lowerBound = mempty
instance Show address => Show (Bindings address) where
showsPrec d = showsUnaryWith showsPrec "Bindings" d . pairs
-- | A LIFO stack of maps of names to addresses, representing a lexically-scoped evaluation environment.
-- All behaviors can be assumed to be frontmost-biased: looking up "a" will check the most specific
-- scope for "a", then the next, and so on.
newtype Environment address = Environment { unEnvironment :: NonEmpty (Bindings address) }
deriving stock (Eq, Ord, Generic)
deriving anyclass (NFData)
data EvalContext address = EvalContext { ctxSelf :: Maybe address, ctxEnvironment :: Environment address }
deriving (Eq, Ord, Show, Generic, NFData)
-- | Errors involving the environment.
data EnvironmentError address return where
FreeVariable :: Name -> EnvironmentError address address
instance NFData1 (EnvironmentError address) where
liftRnf _ (FreeVariable n) = rnf n
instance (NFData return) => NFData (EnvironmentError address return) where
rnf = liftRnf rnf
deriving instance Eq (EnvironmentError address return)
deriving instance Show (EnvironmentError address return)
instance Show1 (EnvironmentError address) where liftShowsPrec _ _ = showsPrec
instance Eq1 (EnvironmentError address) where liftEq _ (FreeVariable n1) (FreeVariable n2) = n1 == n2
instance Lower (EvalContext address) where
lowerBound = EvalContext Nothing lowerBound
-- | Make and enter a new empty scope in the given environment.
push :: Environment address -> Environment address
push (Environment (a :| as)) = Environment (mempty :| a : as)
-- | Remove the frontmost scope.
pop :: Environment address -> Environment address
pop (Environment (_ :| [])) = lowerBound
pop (Environment (_ :| a : as)) = Environment (a :| as)
-- | Return the frontmost (ie. most local) frame of bindings in the environment
head :: Environment address -> Bindings address
head (Environment (a :| _)) = a
-- | Extract an association list of bindings from a 'Bindings'.
--
-- >>> pairs (head shadowed)
-- [("foo",Precise 1)]
pairs :: Bindings address -> [(Name, address)]
pairs = Map.toList . unBindings
unpairs :: [(Name, address)] -> Bindings address
unpairs = Bindings . Map.fromList
flatPairs :: Environment address -> [(Name, address)]
flatPairs = (>>= pairs) . toList . unEnvironment
newEnv :: Bindings address -> Environment address
newEnv = Environment . pure
-- | Lookup a 'Name' in the bindings.
lookup :: Name -> Bindings address -> Maybe address
lookup name = Map.lookup name . unBindings
-- | Lookup a 'Name' in the environment.
lookupEnv' :: Name -> Environment address -> Maybe address
lookupEnv' name = foldMapA (lookup name) . unEnvironment
-- | Insert a 'Name' in the bindings
insert :: Name -> address -> Bindings address -> Bindings address
insert name addr = Bindings . Map.insert name addr . unBindings
-- | Insert a 'Name' in the environment
insertEnv :: Name -> address -> Environment address -> Environment address
insertEnv name addr (Environment (Bindings a :| as)) = Environment (Bindings (Map.insert name addr a) :| as)
-- | Remove a 'Name' from the environment.
delete :: Name -> Environment address -> Environment address
delete name = trim . Environment . fmap (Bindings . Map.delete name . unBindings) . unEnvironment
trim :: Environment address -> Environment address
trim (Environment (a :| as)) = Environment (a :| filtered)
where filtered = filter (not . Map.null . unBindings) as
intersect :: Foldable t => t Name -> Environment address -> Environment address
intersect names env = newEnv (unpairs (mapMaybe lookupName (toList names)))
where
lookupName name = (,) name <$> lookupEnv' name env
-- | Get all bound 'Name's in a binding.
names :: Bindings address -> [Name]
names = fmap fst . pairs
-- | Order preserving deduplication in O(n log n) time
dedup :: Ord a => [a] -> [a]
dedup = go Set.empty
where
go _ [] = []
go seen (x:xs)
| Set.member x seen = go seen xs
| otherwise = x : go (Set.insert x seen) xs
-- | Get all bound 'Name's in an environment.
allNames :: Environment address -> [Name]
allNames = dedup . fmap fst . flatPairs
aliasBindings :: [(Name, Name)] -> Bindings address -> Bindings address
aliasBindings pairs binds = unpairs $ mapMaybe lookupAndAlias pairs
where
lookupAndAlias (oldName, newName) = (,) newName <$> Map.lookup oldName (unBindings binds)
-- | Lookup and alias name-value bindings from an environment.
overwrite :: [(Name, Name)] -> Environment address -> Environment address
overwrite pairs env = newEnv . unpairs $ mapMaybe lookupAndAlias pairs
where
lookupAndAlias (oldName, newName) = (,) newName <$> lookupEnv' oldName env
-- | Retrieve the 'Live' set of addresses to which the given free variable names are bound.
--
-- Unbound names are silently dropped.
roots :: (Ord address, Foldable t) => Environment address -> t Name -> Live address
roots env names = addresses (names `intersect` env)
addresses :: Ord address => Environment address -> Live address
addresses = fromAddresses . map snd . flatPairs
instance Lower (Environment address) where lowerBound = Environment (lowerBound :| [])
-- N.B. this show instance drops some information to avoid generating
-- an infinite string in certain cases. As such, two unequal
-- environments may produce equal outputs over Show.
instance Show address => Show (Environment address) where
showsPrec d = showsUnaryWith showsPrec "Environment" d . flatPairs

View File

@ -7,7 +7,6 @@ module Data.Abstract.Exports
, toBindings
) where
import Data.Abstract.Environment (Bindings, unpairs)
import Data.Abstract.Name
import qualified Data.Map as Map
import Prelude hiding (null)

View File

@ -9,7 +9,6 @@ import qualified Assigning.Assignment.Spec
import qualified Control.Abstract.Evaluator.Spec
import qualified Control.Rewriting.Spec
import qualified Data.Diff.Spec
import qualified Data.Abstract.Environment.Spec
import qualified Data.Abstract.Name.Spec
import qualified Data.Abstract.Path.Spec
import qualified Data.Functor.Classes.Generic.Spec
@ -56,7 +55,6 @@ main = do
describe "Control.Rewriting.Spec" Control.Rewriting.Spec.spec
describe "Data.Diff" Data.Diff.Spec.spec
describe "Data.Graph" Data.Graph.Spec.spec
describe "Data.Abstract.Environment.Spec" Data.Abstract.Environment.Spec.spec
describe "Data.Abstract.Path" Data.Abstract.Path.Spec.spec
describe "Data.Abstract.Name" Data.Abstract.Name.Spec.spec
describe "Data.Functor.Classes.Generic" Data.Functor.Classes.Generic.Spec.spec