mirror of
https://github.com/github/semantic.git
synced 2024-12-23 14:54:16 +03:00
Represent term/value types with type families.
This commit is contained in:
parent
16d03caf3d
commit
b0de8c5830
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Analysis.Abstract.Caching
|
module Analysis.Abstract.Caching
|
||||||
( evaluateCache )
|
( evaluateCache )
|
||||||
where
|
where
|
||||||
@ -29,7 +29,7 @@ type CacheFor term value = Cache (LocationFor value) term value
|
|||||||
newtype CachingAnalysis term value a = CachingAnalysis { runCachingAnalysis :: Evaluator term value (CachingEffects term value) a }
|
newtype CachingAnalysis term value a = CachingAnalysis { runCachingAnalysis :: Evaluator term value (CachingEffects term value) a }
|
||||||
deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFresh, MonadNonDet)
|
deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFresh, MonadNonDet)
|
||||||
|
|
||||||
deriving instance MonadEvaluator term value (CachingAnalysis term value)
|
deriving instance Ord (LocationFor value) => MonadEvaluator (CachingAnalysis term value)
|
||||||
|
|
||||||
-- TODO: reabstract these later on
|
-- TODO: reabstract these later on
|
||||||
|
|
||||||
@ -62,12 +62,12 @@ instance ( Corecursive t
|
|||||||
, Evaluatable (Base t)
|
, Evaluatable (Base t)
|
||||||
, Foldable (Cell (LocationFor v))
|
, Foldable (Cell (LocationFor v))
|
||||||
, FreeVariables t
|
, FreeVariables t
|
||||||
, MonadAddressable (LocationFor v) v (CachingAnalysis t v)
|
, MonadAddressable (LocationFor v) (CachingAnalysis t v)
|
||||||
, MonadValue t v (CachingAnalysis t v)
|
, MonadValue v (CachingAnalysis t v)
|
||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (CellFor v)
|
, Semigroup (CellFor v)
|
||||||
)
|
)
|
||||||
=> MonadAnalysis t v (CachingAnalysis t v) where
|
=> MonadAnalysis (CachingAnalysis t v) where
|
||||||
analyzeTerm e = do
|
analyzeTerm e = do
|
||||||
c <- getConfiguration (embedSubterm e)
|
c <- getConfiguration (embedSubterm e)
|
||||||
-- Convergence here is predicated upon an Eq instance, not α-equivalence
|
-- Convergence here is predicated upon an Eq instance, not α-equivalence
|
||||||
@ -85,6 +85,9 @@ instance ( Corecursive t
|
|||||||
getCache) mempty
|
getCache) mempty
|
||||||
maybe empty scatter (cacheLookup c cache)
|
maybe empty scatter (cacheLookup c cache)
|
||||||
|
|
||||||
|
type instance AnalysisTerm (CachingAnalysis term value) = term
|
||||||
|
type instance AnalysisValue (CachingAnalysis term value) = value
|
||||||
|
|
||||||
|
|
||||||
-- | Coinductively-cached evaluation.
|
-- | Coinductively-cached evaluation.
|
||||||
evaluateCache :: forall v term
|
evaluateCache :: forall v term
|
||||||
@ -98,8 +101,8 @@ evaluateCache :: forall v term
|
|||||||
, Foldable (Cell (LocationFor v))
|
, Foldable (Cell (LocationFor v))
|
||||||
, Functor (Base term)
|
, Functor (Base term)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, MonadAddressable (LocationFor v) v (CachingAnalysis term v)
|
, MonadAddressable (LocationFor v) (CachingAnalysis term v)
|
||||||
, MonadValue term v (CachingAnalysis term v)
|
, MonadValue v (CachingAnalysis term v)
|
||||||
, Semigroup (CellFor v)
|
, Semigroup (CellFor v)
|
||||||
, ValueRoots (LocationFor v) v
|
, ValueRoots (LocationFor v) v
|
||||||
)
|
)
|
||||||
@ -123,7 +126,7 @@ converge f = loop
|
|||||||
loop x'
|
loop x'
|
||||||
|
|
||||||
-- | Nondeterministically write each of a collection of stores & return their associated results.
|
-- | Nondeterministically write each of a collection of stores & return their associated results.
|
||||||
scatter :: (Alternative m, Foldable t, MonadEvaluator term v m) => t (a, Store (LocationFor v) v) -> m a
|
scatter :: (Alternative m, Foldable t, MonadEvaluator m) => t (a, Store (LocationFor (AnalysisValue m)) (AnalysisValue m)) -> m a
|
||||||
scatter = getAlt . foldMap (\ (value, store') -> Alt (putStore store' *> pure value))
|
scatter = getAlt . foldMap (\ (value, store') -> Alt (putStore store' *> pure value))
|
||||||
|
|
||||||
-- | Evaluation of a single iteration of an analysis, given an in-cache as an oracle for results and an out-cache to record computed results in.
|
-- | Evaluation of a single iteration of an analysis, given an in-cache as an oracle for results and an out-cache to record computed results in.
|
||||||
@ -138,8 +141,8 @@ memoizeEval :: forall v term
|
|||||||
, Foldable (Cell (LocationFor v))
|
, Foldable (Cell (LocationFor v))
|
||||||
, Functor (Base term)
|
, Functor (Base term)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, MonadAddressable (LocationFor v) v (CachingAnalysis term v)
|
, MonadAddressable (LocationFor v) (CachingAnalysis term v)
|
||||||
, MonadValue term v (CachingAnalysis term v)
|
, MonadValue v (CachingAnalysis term v)
|
||||||
, Semigroup (CellFor v)
|
, Semigroup (CellFor v)
|
||||||
)
|
)
|
||||||
=> SubtermAlgebra (Base term) term (CachingAnalysis term v v)
|
=> SubtermAlgebra (Base term) term (CachingAnalysis term v v)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Analysis.Abstract.Dead where
|
module Analysis.Abstract.Dead where
|
||||||
|
|
||||||
import Control.Abstract.Addressable
|
import Control.Abstract.Addressable
|
||||||
@ -19,8 +19,8 @@ evaluateDead :: forall term value
|
|||||||
, Evaluatable (Base term)
|
, Evaluatable (Base term)
|
||||||
, Foldable (Base term)
|
, Foldable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value (DeadCodeAnalysis term value)
|
, MonadAddressable (LocationFor value) (DeadCodeAnalysis term value)
|
||||||
, MonadValue term value (DeadCodeAnalysis term value)
|
, MonadValue value (DeadCodeAnalysis term value)
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Ord term
|
, Ord term
|
||||||
, Recursive term
|
, Recursive term
|
||||||
@ -39,7 +39,7 @@ evaluateDead term = run @(DeadCodeEffects term value) . runEvaluator . runDeadCo
|
|||||||
newtype DeadCodeAnalysis term value a = DeadCodeAnalysis { runDeadCodeAnalysis :: Evaluator term value (DeadCodeEffects term value) a }
|
newtype DeadCodeAnalysis term value a = DeadCodeAnalysis { runDeadCodeAnalysis :: Evaluator term value (DeadCodeEffects term value) a }
|
||||||
deriving (Applicative, Functor, Monad, MonadFail)
|
deriving (Applicative, Functor, Monad, MonadFail)
|
||||||
|
|
||||||
deriving instance MonadEvaluator term value (DeadCodeAnalysis term value)
|
deriving instance Ord (LocationFor value) => MonadEvaluator (DeadCodeAnalysis term value)
|
||||||
|
|
||||||
|
|
||||||
-- | A set of “dead” (unreachable) terms.
|
-- | A set of “dead” (unreachable) terms.
|
||||||
@ -60,13 +60,16 @@ revive t = DeadCodeAnalysis (Evaluator (modify (Dead . delete t . unDead)))
|
|||||||
instance ( Corecursive t
|
instance ( Corecursive t
|
||||||
, Evaluatable (Base t)
|
, Evaluatable (Base t)
|
||||||
, FreeVariables t
|
, FreeVariables t
|
||||||
, MonadAddressable (LocationFor v) v (DeadCodeAnalysis t v)
|
, MonadAddressable (LocationFor v) (DeadCodeAnalysis t v)
|
||||||
, MonadValue t v (DeadCodeAnalysis t v)
|
, MonadValue v (DeadCodeAnalysis t v)
|
||||||
, Ord t
|
, Ord t
|
||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (CellFor v)
|
, Semigroup (CellFor v)
|
||||||
)
|
)
|
||||||
=> MonadAnalysis t v (DeadCodeAnalysis t v) where
|
=> MonadAnalysis (DeadCodeAnalysis t v) where
|
||||||
analyzeTerm term = do
|
analyzeTerm term = do
|
||||||
revive (embedSubterm term)
|
revive (embedSubterm term)
|
||||||
eval term
|
eval term
|
||||||
|
|
||||||
|
type instance AnalysisTerm (DeadCodeAnalysis term value) = term
|
||||||
|
type instance AnalysisValue (DeadCodeAnalysis term value) = value
|
||||||
|
@ -15,8 +15,8 @@ import System.FilePath.Posix
|
|||||||
evaluate :: forall value term
|
evaluate :: forall value term
|
||||||
. ( Evaluatable (Base term)
|
. ( Evaluatable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value (Evaluation term value)
|
, MonadAddressable (LocationFor value) (Evaluation term value)
|
||||||
, MonadValue term value (Evaluation term value)
|
, MonadValue value (Evaluation term value)
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
@ -29,8 +29,8 @@ evaluate = run @(EvaluatorEffects term value) . runEvaluator . runEvaluation . e
|
|||||||
evaluates :: forall value term
|
evaluates :: forall value term
|
||||||
. ( Evaluatable (Base term)
|
. ( Evaluatable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value (Evaluation term value)
|
, MonadAddressable (LocationFor value) (Evaluation term value)
|
||||||
, MonadValue term value (Evaluation term value)
|
, MonadValue value (Evaluation term value)
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
@ -41,7 +41,7 @@ evaluates :: forall value term
|
|||||||
evaluates pairs (_, t) = run @(EvaluatorEffects term value) (runEvaluator (runEvaluation (withModules pairs (evaluateTerm t))))
|
evaluates pairs (_, t) = run @(EvaluatorEffects term value) (runEvaluator (runEvaluation (withModules pairs (evaluateTerm t))))
|
||||||
|
|
||||||
-- | Run an action with the passed ('Blob', @term@) pairs available for imports.
|
-- | Run an action with the passed ('Blob', @term@) pairs available for imports.
|
||||||
withModules :: (MonadAnalysis term value m, MonadEvaluator term value m) => [(Blob, term)] -> m a -> m a
|
withModules :: (MonadAnalysis m, MonadEvaluator m) => [(Blob, AnalysisTerm m)] -> m a -> m a
|
||||||
withModules pairs = localModuleTable (const moduleTable)
|
withModules pairs = localModuleTable (const moduleTable)
|
||||||
where moduleTable = Linker (Map.fromList (map (first (dropExtensions . blobPath)) pairs))
|
where moduleTable = Linker (Map.fromList (map (first (dropExtensions . blobPath)) pairs))
|
||||||
|
|
||||||
@ -49,14 +49,17 @@ withModules pairs = localModuleTable (const moduleTable)
|
|||||||
newtype Evaluation term value a = Evaluation { runEvaluation :: Evaluator term value (EvaluatorEffects term value) a }
|
newtype Evaluation term value a = Evaluation { runEvaluation :: Evaluator term value (EvaluatorEffects term value) a }
|
||||||
deriving (Applicative, Functor, Monad, MonadFail)
|
deriving (Applicative, Functor, Monad, MonadFail)
|
||||||
|
|
||||||
deriving instance MonadEvaluator term value (Evaluation term value)
|
deriving instance Ord (LocationFor value) => MonadEvaluator (Evaluation term value)
|
||||||
|
|
||||||
instance ( Evaluatable (Base term)
|
instance ( Evaluatable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value (Evaluation term value)
|
, MonadAddressable (LocationFor value) (Evaluation term value)
|
||||||
, MonadValue term value (Evaluation term value)
|
, MonadValue value (Evaluation term value)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
)
|
)
|
||||||
=> MonadAnalysis term value (Evaluation term value) where
|
=> MonadAnalysis (Evaluation term value) where
|
||||||
analyzeTerm = eval
|
analyzeTerm = eval
|
||||||
|
|
||||||
|
type instance AnalysisTerm (Evaluation term value) = term
|
||||||
|
type instance AnalysisValue (Evaluation term value) = value
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, KindSignatures, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Analysis.Abstract.Tracing where
|
module Analysis.Abstract.Tracing where
|
||||||
|
|
||||||
import Control.Abstract.Addressable
|
import Control.Abstract.Addressable
|
||||||
@ -26,11 +26,13 @@ evaluateTrace :: forall trace value term
|
|||||||
, Ord (CellFor value)
|
, Ord (CellFor value)
|
||||||
, Ord term
|
, Ord term
|
||||||
, Ord value
|
, Ord value
|
||||||
|
, AnalysisTerm (Evaluator term value (TracingEffects trace term value)) ~ term
|
||||||
|
, AnalysisValue (Evaluator term value (TracingEffects trace term value)) ~ value
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Reducer (ConfigurationFor term value) trace
|
, Reducer (ConfigurationFor term value) trace
|
||||||
, MonadAddressable (LocationFor value) value (TracingAnalysis trace Evaluator term value (TracingEffects trace term value))
|
, MonadAddressable (LocationFor value) (TracingAnalysis trace (Evaluator term value) term value (TracingEffects trace term value))
|
||||||
, MonadAnalysis term value (Evaluator term value (TracingEffects trace term value))
|
, MonadAnalysis (Evaluator term value (TracingEffects trace term value))
|
||||||
, MonadValue term value (TracingAnalysis trace Evaluator term value (TracingEffects trace term value))
|
, MonadValue value (TracingAnalysis trace (Evaluator term value) term value (TracingEffects trace term value))
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
)
|
)
|
||||||
=> term
|
=> term
|
||||||
@ -39,27 +41,32 @@ evaluateTrace = run @(TracingEffects trace term value) . runEvaluator . runTraci
|
|||||||
|
|
||||||
|
|
||||||
newtype TracingAnalysis trace underlying term value (effects :: [* -> *]) a
|
newtype TracingAnalysis trace underlying term value (effects :: [* -> *]) a
|
||||||
= TracingAnalysis { runTracingAnalysis :: underlying term value effects a }
|
= TracingAnalysis { runTracingAnalysis :: underlying effects a }
|
||||||
deriving (Applicative, Functor, LiftEffect, Monad, MonadFail)
|
deriving (Applicative, Functor, LiftEffect, Monad, MonadFail)
|
||||||
|
|
||||||
deriving instance MonadEvaluator term value (underlying term value effects) => MonadEvaluator term value (TracingAnalysis trace underlying term value effects)
|
deriving instance (AnalysisTerm (underlying effects) ~ term, AnalysisValue (underlying effects) ~ value, MonadEvaluator (underlying effects)) => MonadEvaluator (TracingAnalysis trace underlying term value effects)
|
||||||
|
|
||||||
instance ( Corecursive term
|
instance ( Corecursive term
|
||||||
, Evaluatable (Base term)
|
, Evaluatable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, LiftEffect (underlying term value)
|
, LiftEffect underlying
|
||||||
, Member (Writer trace) effects
|
, Member (Writer trace) effects
|
||||||
, MonadAddressable (LocationFor value) value (TracingAnalysis trace underlying term value effects)
|
, MonadAddressable (LocationFor value) (TracingAnalysis trace underlying term value effects)
|
||||||
, MonadAnalysis term value (underlying term value effects)
|
, MonadAnalysis (underlying effects)
|
||||||
, MonadValue term value (TracingAnalysis trace underlying term value effects)
|
, AnalysisTerm (underlying effects) ~ term
|
||||||
|
, AnalysisValue (underlying effects) ~ value
|
||||||
|
, MonadValue value (TracingAnalysis trace underlying term value effects)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Reducer (ConfigurationFor term value) trace
|
, Reducer (ConfigurationFor term value) trace
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
)
|
)
|
||||||
=> MonadAnalysis term value (TracingAnalysis trace underlying term value effects) where
|
=> MonadAnalysis (TracingAnalysis trace underlying term value effects) where
|
||||||
analyzeTerm term = getConfiguration (embedSubterm term) >>= trace . Reducer.unit >> analyzeTerm term
|
analyzeTerm term = getConfiguration (embedSubterm term) >>= trace . Reducer.unit >> analyzeTerm term
|
||||||
|
|
||||||
trace :: (LiftEffect (underlying term value), Member (Writer trace) effects)
|
type instance AnalysisTerm (TracingAnalysis trace underlying term value effects) = term
|
||||||
|
type instance AnalysisValue (TracingAnalysis trace underlying term value effects) = value
|
||||||
|
|
||||||
|
trace :: (LiftEffect underlying, Member (Writer trace) effects)
|
||||||
=> trace
|
=> trace
|
||||||
-> TracingAnalysis trace underlying term value effects ()
|
-> TracingAnalysis trace underlying term value effects ()
|
||||||
trace w = lift (tell w)
|
trace w = lift (tell w)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{-# LANGUAGE FunctionalDependencies, TypeFamilies, UndecidableInstances #-}
|
{-# LANGUAGE FunctionalDependencies, TypeFamilies, UndecidableInstances #-}
|
||||||
module Control.Abstract.Addressable where
|
module Control.Abstract.Addressable where
|
||||||
|
|
||||||
|
import Control.Abstract.Analysis
|
||||||
import Control.Abstract.Evaluator
|
import Control.Abstract.Evaluator
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Monad ((<=<))
|
import Control.Monad ((<=<))
|
||||||
import Control.Monad.Effect.Fail
|
|
||||||
import Data.Abstract.Address
|
import Data.Abstract.Address
|
||||||
import Data.Abstract.Environment
|
import Data.Abstract.Environment
|
||||||
import Data.Abstract.FreeVariables
|
import Data.Abstract.FreeVariables
|
||||||
@ -16,19 +16,20 @@ import Data.Semigroup.Reducer
|
|||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
|
||||||
-- | Defines 'alloc'ation and 'deref'erencing of 'Address'es in a Store.
|
-- | Defines 'alloc'ation and 'deref'erencing of 'Address'es in a Store.
|
||||||
class (Monad m, Ord l, l ~ LocationFor a, Reducer a (Cell l a)) => MonadAddressable l a m | m -> a where
|
class (Monad m, Ord l, l ~ LocationFor (AnalysisValue m), Reducer (AnalysisValue m) (Cell l (AnalysisValue m))) => MonadAddressable l m where
|
||||||
deref :: Address l a
|
deref :: Address l (AnalysisValue m)
|
||||||
-> m a
|
-> m (AnalysisValue m)
|
||||||
|
|
||||||
alloc :: Name
|
alloc :: Name
|
||||||
-> m (Address l a)
|
-> m (Address l (AnalysisValue m))
|
||||||
|
|
||||||
-- | Look up or allocate an address for a 'Name' free in a given term & assign it a given value, returning the 'Name' paired with the address.
|
-- | Look up or allocate an address for a 'Name' free in a given term & assign it a given value, returning the 'Name' paired with the address.
|
||||||
--
|
--
|
||||||
-- The term is expected to contain one and only one free 'Name', meaning that care should be taken to apply this only to e.g. identifiers.
|
-- The term is expected to contain one and only one free 'Name', meaning that care should be taken to apply this only to e.g. identifiers.
|
||||||
lookupOrAlloc :: ( FreeVariables t
|
lookupOrAlloc :: ( FreeVariables t
|
||||||
, MonadAddressable (LocationFor a) a m
|
, MonadAddressable (LocationFor a) m
|
||||||
, MonadEvaluator t a m
|
, MonadEvaluator m
|
||||||
|
, a ~ AnalysisValue m
|
||||||
, Semigroup (CellFor a)
|
, Semigroup (CellFor a)
|
||||||
)
|
)
|
||||||
=> t
|
=> t
|
||||||
@ -40,8 +41,9 @@ lookupOrAlloc term = let [name] = toList (freeVariables term) in
|
|||||||
where
|
where
|
||||||
-- | Look up or allocate an address for a 'Name' & assign it a given value, returning the 'Name' paired with the address.
|
-- | Look up or allocate an address for a 'Name' & assign it a given value, returning the 'Name' paired with the address.
|
||||||
lookupOrAlloc' :: ( Semigroup (CellFor a)
|
lookupOrAlloc' :: ( Semigroup (CellFor a)
|
||||||
, MonadAddressable (LocationFor a) a m
|
, MonadAddressable (LocationFor a) m
|
||||||
, MonadEvaluator t a m
|
, a ~ AnalysisValue m
|
||||||
|
, MonadEvaluator m
|
||||||
)
|
)
|
||||||
=> Name
|
=> Name
|
||||||
-> a
|
-> a
|
||||||
@ -54,7 +56,8 @@ lookupOrAlloc term = let [name] = toList (freeVariables term) in
|
|||||||
|
|
||||||
-- | Write a value to the given 'Address' in the 'Store'.
|
-- | Write a value to the given 'Address' in the 'Store'.
|
||||||
assign :: ( Ord (LocationFor a)
|
assign :: ( Ord (LocationFor a)
|
||||||
, MonadEvaluator t a m
|
, MonadEvaluator m
|
||||||
|
, a ~ AnalysisValue m
|
||||||
, Reducer a (CellFor a)
|
, Reducer a (CellFor a)
|
||||||
)
|
)
|
||||||
=> Address (LocationFor a) a
|
=> Address (LocationFor a) a
|
||||||
@ -66,7 +69,7 @@ assign address = modifyStore . storeInsert address
|
|||||||
-- Instances
|
-- Instances
|
||||||
|
|
||||||
-- | 'Precise' locations are always 'alloc'ated a fresh 'Address', and 'deref'erence to the 'Latest' value written.
|
-- | 'Precise' locations are always 'alloc'ated a fresh 'Address', and 'deref'erence to the 'Latest' value written.
|
||||||
instance (Monad m, MonadEvaluator t v m, LocationFor v ~ Precise) => MonadAddressable Precise v m where
|
instance (Monad m, MonadEvaluator m, LocationFor (AnalysisValue m) ~ Precise) => MonadAddressable Precise m where
|
||||||
deref = maybe uninitializedAddress (pure . unLatest) <=< flip fmap getStore . storeLookup
|
deref = maybe uninitializedAddress (pure . unLatest) <=< flip fmap getStore . storeLookup
|
||||||
where
|
where
|
||||||
-- | Fail with a message denoting an uninitialized address (i.e. one which was 'alloc'ated, but never 'assign'ed a value before being 'deref'erenced).
|
-- | Fail with a message denoting an uninitialized address (i.e. one which was 'alloc'ated, but never 'assign'ed a value before being 'deref'erenced).
|
||||||
@ -77,7 +80,7 @@ instance (Monad m, MonadEvaluator t v m, LocationFor v ~ Precise) => MonadAddres
|
|||||||
|
|
||||||
|
|
||||||
-- | 'Monovariant' locations 'alloc'ate one 'Address' per unique variable name, and 'deref'erence once per stored value, nondeterministically.
|
-- | 'Monovariant' locations 'alloc'ate one 'Address' per unique variable name, and 'deref'erence once per stored value, nondeterministically.
|
||||||
instance (Alternative m, Ord v, LocationFor v ~ Monovariant, Monad m, MonadEvaluator t v m) => MonadAddressable Monovariant v m where
|
instance (Alternative m, Ord (AnalysisValue m), LocationFor (AnalysisValue m) ~ Monovariant, Monad m, MonadEvaluator m) => MonadAddressable Monovariant m where
|
||||||
deref = asum . maybe [] (map pure . toList) <=< flip fmap getStore . storeLookup
|
deref = asum . maybe [] (map pure . toList) <=< flip fmap getStore . storeLookup
|
||||||
|
|
||||||
alloc = pure . Address . Monovariant
|
alloc = pure . Address . Monovariant
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{-# LANGUAGE DefaultSignatures, FunctionalDependencies #-}
|
{-# LANGUAGE DefaultSignatures, KindSignatures, TypeFamilies #-}
|
||||||
module Control.Abstract.Analysis
|
module Control.Abstract.Analysis
|
||||||
( MonadAnalysis(..)
|
( MonadAnalysis(..)
|
||||||
|
, AnalysisTerm
|
||||||
|
, AnalysisValue
|
||||||
, module X
|
, module X
|
||||||
, Subterm(..)
|
, Subterm(..)
|
||||||
, SubtermAlgebra
|
, SubtermAlgebra
|
||||||
@ -12,16 +14,19 @@ import Control.Monad.Effect.Reader as X
|
|||||||
import Control.Monad.Effect.State as X
|
import Control.Monad.Effect.State as X
|
||||||
import Prologue
|
import Prologue
|
||||||
|
|
||||||
|
type family AnalysisTerm (m :: * -> *)
|
||||||
|
type family AnalysisValue (m :: * -> *)
|
||||||
|
|
||||||
-- | A 'Monad' in which one can evaluate some specific term type to some specific value type.
|
-- | A 'Monad' in which one can evaluate some specific term type to some specific value type.
|
||||||
--
|
--
|
||||||
-- This typeclass is left intentionally unconstrained to avoid circular dependencies between it and other typeclasses.
|
-- This typeclass is left intentionally unconstrained to avoid circular dependencies between it and other typeclasses.
|
||||||
class Monad m => MonadAnalysis term value m | m -> term, m -> value where
|
class Monad m => MonadAnalysis m where
|
||||||
-- | Analyze a term using the semantics of the current analysis. This should generally only be called by definitions of 'evaluateTerm' and 'analyzeTerm' in this or other instances.
|
-- | Analyze a term using the semantics of the current analysis. This should generally only be called by definitions of 'evaluateTerm' and 'analyzeTerm' in this or other instances.
|
||||||
analyzeTerm :: SubtermAlgebra (Base term) term (m value)
|
analyzeTerm :: SubtermAlgebra (Base (AnalysisTerm m)) (AnalysisTerm m) (m (AnalysisValue m))
|
||||||
|
|
||||||
-- | Evaluate a term to a value using the semantics of the current analysis.
|
-- | Evaluate a term to a value using the semantics of the current analysis.
|
||||||
--
|
--
|
||||||
-- This should always be called instead of explicitly folding either 'eval' or 'analyzeTerm' over subterms, except in 'MonadAnalysis' instances themselves.
|
-- This should always be called instead of explicitly folding either 'eval' or 'analyzeTerm' over subterms, except in 'MonadAnalysis' instances themselves.
|
||||||
evaluateTerm :: term -> m value
|
evaluateTerm :: AnalysisTerm m -> m (AnalysisValue m)
|
||||||
default evaluateTerm :: Recursive term => term -> m value
|
default evaluateTerm :: Recursive (AnalysisTerm m) => AnalysisTerm m -> m (AnalysisValue m)
|
||||||
evaluateTerm = foldSubterms analyzeTerm
|
evaluateTerm = foldSubterms analyzeTerm
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
{-# LANGUAGE DataKinds, DefaultSignatures, FunctionalDependencies, GeneralizedNewtypeDeriving, RankNTypes, StandaloneDeriving, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, DefaultSignatures, GeneralizedNewtypeDeriving, RankNTypes, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}
|
||||||
module Control.Abstract.Evaluator where
|
module Control.Abstract.Evaluator where
|
||||||
|
|
||||||
|
import Control.Abstract.Analysis
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Effect
|
|
||||||
import Control.Monad.Effect
|
import Control.Monad.Effect
|
||||||
import Control.Monad.Effect.Fail
|
|
||||||
import Control.Monad.Effect.Fresh
|
import Control.Monad.Effect.Fresh
|
||||||
import Control.Monad.Effect.NonDet
|
import Control.Monad.Effect.NonDet
|
||||||
import Control.Monad.Effect.Reader
|
|
||||||
import Control.Monad.Effect.State
|
|
||||||
import Data.Abstract.Configuration
|
import Data.Abstract.Configuration
|
||||||
import Data.Abstract.Linker
|
import Data.Abstract.Linker
|
||||||
import Data.Abstract.Live
|
import Data.Abstract.Live
|
||||||
@ -21,38 +18,38 @@ import Prelude hiding (fail)
|
|||||||
-- - environments binding names to addresses
|
-- - environments binding names to addresses
|
||||||
-- - a heap mapping addresses to (possibly sets of) values
|
-- - a heap mapping addresses to (possibly sets of) values
|
||||||
-- - tables of modules available for import
|
-- - tables of modules available for import
|
||||||
class MonadFail m => MonadEvaluator term value m | m -> term, m -> value where
|
class (MonadFail m, Ord (LocationFor (AnalysisValue m))) => MonadEvaluator m where
|
||||||
-- | Retrieve the global environment.
|
-- | Retrieve the global environment.
|
||||||
getGlobalEnv :: m (EnvironmentFor value)
|
getGlobalEnv :: m (EnvironmentFor (AnalysisValue m))
|
||||||
-- | Update the global environment.
|
-- | Update the global environment.
|
||||||
modifyGlobalEnv :: (EnvironmentFor value -> EnvironmentFor value) -> m ()
|
modifyGlobalEnv :: (EnvironmentFor (AnalysisValue m) -> EnvironmentFor (AnalysisValue m)) -> m ()
|
||||||
|
|
||||||
-- | Retrieve the local environment.
|
-- | Retrieve the local environment.
|
||||||
askLocalEnv :: m (EnvironmentFor value)
|
askLocalEnv :: m (EnvironmentFor (AnalysisValue m))
|
||||||
-- | Run an action with a locally-modified environment.
|
-- | Run an action with a locally-modified environment.
|
||||||
localEnv :: (EnvironmentFor value -> EnvironmentFor value) -> m a -> m a
|
localEnv :: (EnvironmentFor (AnalysisValue m) -> EnvironmentFor (AnalysisValue m)) -> m a -> m a
|
||||||
|
|
||||||
-- | Retrieve the heap.
|
-- | Retrieve the heap.
|
||||||
getStore :: m (StoreFor value)
|
getStore :: m (StoreFor (AnalysisValue m))
|
||||||
-- | Update the heap.
|
-- | Update the heap.
|
||||||
modifyStore :: (StoreFor value -> StoreFor value) -> m ()
|
modifyStore :: (StoreFor (AnalysisValue m) -> StoreFor (AnalysisValue m)) -> m ()
|
||||||
|
|
||||||
-- | Retrieve the table of evaluated modules.
|
-- | Retrieve the table of evaluated modules.
|
||||||
getModuleTable :: m (Linker value)
|
getModuleTable :: m (Linker (AnalysisValue m))
|
||||||
-- | Update the table of evaluated modules.
|
-- | Update the table of evaluated modules.
|
||||||
modifyModuleTable :: (Linker value -> Linker value) -> m ()
|
modifyModuleTable :: (Linker (AnalysisValue m) -> Linker (AnalysisValue m)) -> m ()
|
||||||
|
|
||||||
-- | Retrieve the table of unevaluated modules.
|
-- | Retrieve the table of unevaluated modules.
|
||||||
askModuleTable :: m (Linker term)
|
askModuleTable :: m (Linker (AnalysisTerm m))
|
||||||
-- | Run an action with a locally-modified table of unevaluated modules.
|
-- | Run an action with a locally-modified table of unevaluated modules.
|
||||||
localModuleTable :: (Linker term -> Linker term) -> m a -> m a
|
localModuleTable :: (Linker (AnalysisTerm m) -> Linker (AnalysisTerm m)) -> m a -> m a
|
||||||
|
|
||||||
-- | Retrieve the current root set.
|
-- | Retrieve the current root set.
|
||||||
askRoots :: Ord (LocationFor value) => m (Live (LocationFor value) value)
|
askRoots :: m (Live (LocationFor (AnalysisValue m)) (AnalysisValue m))
|
||||||
askRoots = pure mempty
|
askRoots = pure mempty
|
||||||
|
|
||||||
-- | Get the current 'Configuration' with a passed-in term.
|
-- | Get the current 'Configuration' with a passed-in term.
|
||||||
getConfiguration :: Ord (LocationFor value) => term -> m (Configuration (LocationFor value) term value)
|
getConfiguration :: term -> m (Configuration (LocationFor (AnalysisValue m)) term (AnalysisValue m))
|
||||||
getConfiguration term = Configuration term <$> askRoots <*> askLocalEnv <*> getStore
|
getConfiguration term = Configuration term <$> askRoots <*> askLocalEnv <*> getStore
|
||||||
|
|
||||||
type EvaluatorEffects term value
|
type EvaluatorEffects term value
|
||||||
@ -64,7 +61,9 @@ type EvaluatorEffects term value
|
|||||||
, State (Linker value) -- Cache of evaluated modules
|
, State (Linker value) -- Cache of evaluated modules
|
||||||
]
|
]
|
||||||
|
|
||||||
instance Members (EvaluatorEffects term value) effects => MonadEvaluator term value (Evaluator term value effects) where
|
type instance AnalysisTerm (Evaluator term value effects) = term
|
||||||
|
type instance AnalysisValue (Evaluator term value effects) = value
|
||||||
|
instance (Ord (LocationFor value), Members (EvaluatorEffects term value) effects) => MonadEvaluator (Evaluator term value effects) where
|
||||||
getGlobalEnv = Evaluator get
|
getGlobalEnv = Evaluator get
|
||||||
modifyGlobalEnv f = Evaluator (modify f)
|
modifyGlobalEnv f = Evaluator (modify f)
|
||||||
|
|
||||||
@ -80,7 +79,7 @@ instance Members (EvaluatorEffects term value) effects => MonadEvaluator term va
|
|||||||
askModuleTable = Evaluator ask
|
askModuleTable = Evaluator ask
|
||||||
localModuleTable f a = Evaluator (local f (runEvaluator a))
|
localModuleTable f a = Evaluator (local f (runEvaluator a))
|
||||||
|
|
||||||
putStore :: MonadEvaluator t value m => StoreFor value -> m ()
|
putStore :: MonadEvaluator m => StoreFor (AnalysisValue m) -> m ()
|
||||||
putStore = modifyStore . const
|
putStore = modifyStore . const
|
||||||
|
|
||||||
-- | An evaluator of @term@s to @value@s, producing incremental results of type @a@ using a list of @effects@.
|
-- | An evaluator of @term@s to @value@s, producing incremental results of type @a@ using a list of @effects@.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances #-}
|
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, UndecidableInstances #-}
|
||||||
module Control.Abstract.Value where
|
module Control.Abstract.Value where
|
||||||
|
|
||||||
import Control.Abstract.Addressable
|
import Control.Abstract.Addressable
|
||||||
@ -16,7 +16,7 @@ import Prelude hiding (fail)
|
|||||||
-- | A 'Monad' abstracting the evaluation of (and under) binding constructs (functions, methods, etc).
|
-- | A 'Monad' abstracting the evaluation of (and under) binding constructs (functions, methods, etc).
|
||||||
--
|
--
|
||||||
-- This allows us to abstract the choice of whether to evaluate under binders for different value types.
|
-- This allows us to abstract the choice of whether to evaluate under binders for different value types.
|
||||||
class (MonadEvaluator t v m) => MonadValue t v m where
|
class (MonadEvaluator m, v ~ AnalysisValue m) => MonadValue v m where
|
||||||
-- | Construct an abstract unit value.
|
-- | Construct an abstract unit value.
|
||||||
unit :: m v
|
unit :: m v
|
||||||
|
|
||||||
@ -33,19 +33,21 @@ class (MonadEvaluator t v m) => MonadValue t v m where
|
|||||||
ifthenelse :: v -> m v -> m v -> m v
|
ifthenelse :: v -> m v -> m v -> m v
|
||||||
|
|
||||||
-- | Evaluate an abstraction (a binder like a lambda or method definition).
|
-- | Evaluate an abstraction (a binder like a lambda or method definition).
|
||||||
abstract :: [Name] -> Subterm t (m v) -> m v
|
abstract :: [Name] -> Subterm (AnalysisTerm m) (m v) -> m v
|
||||||
-- | Evaluate an application (like a function call).
|
-- | Evaluate an application (like a function call).
|
||||||
apply :: v -> [Subterm t (m v)] -> m v
|
apply :: v -> [Subterm (AnalysisTerm m) (m v)] -> m v
|
||||||
|
|
||||||
-- | Construct a 'Value' wrapping the value arguments (if any).
|
-- | Construct a 'Value' wrapping the value arguments (if any).
|
||||||
instance ( FreeVariables t
|
instance ( FreeVariables t
|
||||||
, MonadAddressable location (Value location t) m
|
, MonadAddressable location m
|
||||||
, MonadAnalysis t (Value location t) m
|
, MonadAnalysis m
|
||||||
, MonadEvaluator t (Value location t) m
|
, AnalysisTerm m ~ t
|
||||||
|
, AnalysisValue m ~ Value location t
|
||||||
|
, MonadEvaluator m
|
||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (Cell location (Value location t))
|
, Semigroup (Cell location (Value location t))
|
||||||
)
|
)
|
||||||
=> MonadValue t (Value location t) m where
|
=> MonadValue (Value location t) m where
|
||||||
|
|
||||||
unit = pure $ inj Value.Unit
|
unit = pure $ inj Value.Unit
|
||||||
integer = pure . inj . Integer
|
integer = pure . inj . Integer
|
||||||
@ -68,7 +70,7 @@ instance ( FreeVariables t
|
|||||||
localEnv (mappend bindings) (evaluateTerm body)
|
localEnv (mappend bindings) (evaluateTerm body)
|
||||||
|
|
||||||
-- | Discard the value arguments (if any), constructing a 'Type.Type' instead.
|
-- | Discard the value arguments (if any), constructing a 'Type.Type' instead.
|
||||||
instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadValue t Type m where
|
instance (Alternative m, MonadEvaluator m, MonadFresh m, AnalysisValue m ~ Type) => MonadValue Type m where
|
||||||
abstract names (Subterm _ body) = do
|
abstract names (Subterm _ body) = do
|
||||||
(env, tvars) <- foldr (\ name rest -> do
|
(env, tvars) <- foldr (\ name rest -> do
|
||||||
a <- alloc name
|
a <- alloc name
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE DefaultSignatures, FunctionalDependencies, UndecidableInstances #-}
|
{-# LANGUAGE DefaultSignatures, FunctionalDependencies, TypeFamilies, UndecidableInstances #-}
|
||||||
module Data.Abstract.Evaluatable
|
module Data.Abstract.Evaluatable
|
||||||
( Evaluatable(..)
|
( Evaluatable(..)
|
||||||
, module Addressable
|
, module Addressable
|
||||||
@ -30,10 +30,12 @@ import Prologue
|
|||||||
-- | The 'Evaluatable' class defines the necessary interface for a term to be evaluated. While a default definition of 'eval' is given, instances with computational content must implement 'eval' to perform their small-step operational semantics.
|
-- | The 'Evaluatable' class defines the necessary interface for a term to be evaluated. While a default definition of 'eval' is given, instances with computational content must implement 'eval' to perform their small-step operational semantics.
|
||||||
class Evaluatable constr where
|
class Evaluatable constr where
|
||||||
eval :: ( FreeVariables term
|
eval :: ( FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value m
|
, MonadAddressable (LocationFor value) m
|
||||||
, MonadAnalysis term value m
|
, MonadAnalysis m
|
||||||
, MonadEvaluator term value m
|
, AnalysisTerm m ~ term
|
||||||
, MonadValue term value m
|
, AnalysisValue m ~ value
|
||||||
|
, MonadEvaluator m
|
||||||
|
, MonadValue value m
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Semigroup (CellFor value)
|
, Semigroup (CellFor value)
|
||||||
)
|
)
|
||||||
@ -75,24 +77,24 @@ instance Evaluatable [] where
|
|||||||
-- | Require/import another term/file and return an Effect.
|
-- | Require/import another term/file and return an Effect.
|
||||||
--
|
--
|
||||||
-- Looks up the term's name in the cache of evaluated modules first, returns a value if found, otherwise loads/evaluates the module.
|
-- Looks up the term's name in the cache of evaluated modules first, returns a value if found, otherwise loads/evaluates the module.
|
||||||
require :: ( FreeVariables term
|
require :: ( FreeVariables (AnalysisTerm m)
|
||||||
, MonadAnalysis term v m
|
, MonadAnalysis m
|
||||||
, MonadEvaluator term v m
|
, MonadEvaluator m
|
||||||
)
|
)
|
||||||
=> term
|
=> AnalysisTerm m
|
||||||
-> m v
|
-> m (AnalysisValue m)
|
||||||
require term = getModuleTable >>= maybe (load term) pure . linkerLookup name
|
require term = getModuleTable >>= maybe (load term) pure . linkerLookup name
|
||||||
where name = moduleName term
|
where name = moduleName term
|
||||||
|
|
||||||
-- | Load another term/file and return an Effect.
|
-- | Load another term/file and return an Effect.
|
||||||
--
|
--
|
||||||
-- Always loads/evaluates.
|
-- Always loads/evaluates.
|
||||||
load :: ( FreeVariables term
|
load :: ( FreeVariables (AnalysisTerm m)
|
||||||
, MonadAnalysis term v m
|
, MonadAnalysis m
|
||||||
, MonadEvaluator term v m
|
, MonadEvaluator m
|
||||||
)
|
)
|
||||||
=> term
|
=> AnalysisTerm m
|
||||||
-> m v
|
-> m (AnalysisValue m)
|
||||||
load term = askModuleTable >>= maybe notFound evalAndCache . linkerLookup name
|
load term = askModuleTable >>= maybe notFound evalAndCache . linkerLookup name
|
||||||
where name = moduleName term
|
where name = moduleName term
|
||||||
notFound = fail ("cannot find " <> show name)
|
notFound = fail ("cannot find " <> show name)
|
||||||
|
Loading…
Reference in New Issue
Block a user