1
1
mirror of https://github.com/github/semantic.git synced 2025-01-06 23:46:21 +03:00

Merge branch 'master' into scope-graph-indexer

This commit is contained in:
Rick Winfrey 2019-03-11 11:04:27 -07:00
commit 5368c6b37b
66 changed files with 1073 additions and 1093 deletions

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: basement name: basement
version: 0.0.8 version: 0.0.10
summary: Foundation scrap box of array & string summary: Foundation scrap box of array & string
homepage: https://github.com/haskell-foundation/foundation homepage: https://github.com/haskell-foundation/foundation
license: bsd-3-clause license: bsd-3-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: cereal name: cereal
version: 0.5.7.0 version: 0.5.8.0
summary: A binary serialization library summary: A binary serialization library
homepage: https://github.com/GaloisInc/cereal homepage: https://github.com/GaloisInc/cereal
license: bsd-3-clause license: bsd-3-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: fused-effects name: fused-effects
version: 0.1.2.1 version: 0.2.0.1
summary: A fast, flexible, fused effect system. summary: A fast, flexible, fused effect system.
homepage: https://github.com/robrix/fused-effects homepage: https://github.com/robrix/fused-effects
license: bsd-3-clause license: bsd-3-clause
@ -34,4 +34,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: haskeline name: haskeline
version: 0.7.4.3 version: 0.7.5.0
summary: A command-line interface for user input, written in Haskell. summary: A command-line interface for user input, written in Haskell.
homepage: https://github.com/judah/haskeline homepage: https://github.com/judah/haskeline
license: bsd-2-clause license: bsd-2-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: parser-combinators name: parser-combinators
version: 1.0.0 version: 1.0.1
summary: Lightweight package providing commonly useful parser combinators summary: Lightweight package providing commonly useful parser combinators
homepage: https://github.com/mrkkrp/parser-combinators homepage: https://github.com/mrkkrp/parser-combinators
license: bsd-3-clause license: bsd-3-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: recursion-schemes name: recursion-schemes
version: '5.1' version: 5.1.1
summary: Generalized bananas, lenses and barbed wire summary: Generalized bananas, lenses and barbed wire
homepage: https://github.com/ekmett/recursion-schemes/ homepage: https://github.com/ekmett/recursion-schemes/
license: bsd-2-clause license: bsd-2-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: semigroupoids name: semigroupoids
version: 5.3.1 version: 5.3.2
summary: 'Semigroupoids: Category sans id' summary: 'Semigroupoids: Category sans id'
homepage: https://github.com/ekmett/semigroupoids homepage: https://github.com/ekmett/semigroupoids
license: bsd-2-clause license: bsd-2-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: swagger2 name: swagger2
version: 2.3.1 version: 2.3.1.1
summary: Swagger 2.0 data model summary: Swagger 2.0 data model
homepage: https://github.com/GetShopTV/swagger2 homepage: https://github.com/GetShopTV/swagger2
license: bsd-3-clause license: bsd-3-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: these name: these
version: 0.7.5 version: 0.7.6
summary: An either-or-both data type & a generalized 'zip with padding' typeclass summary: An either-or-both data type & a generalized 'zip with padding' typeclass
homepage: https://github.com/isomorphism/these homepage: https://github.com/isomorphism/these
license: bsd-3-clause license: bsd-3-clause

View File

@ -1,7 +1,7 @@
--- ---
type: cabal type: cabal
name: vector-builder name: vector-builder
version: 0.3.6 version: 0.3.7.2
summary: Vector builder summary: Vector builder
homepage: https://github.com/nikita-volkov/vector-builder homepage: https://github.com/nikita-volkov/vector-builder
license: mit license: mit

View File

@ -239,7 +239,7 @@ library
-- API -- API
, Semantic.Api , Semantic.Api
, Semantic.Api.Diffs , Semantic.Api.Diffs
, Semantic.Api.Helpers , Semantic.Api.Bridge
, Semantic.Api.LegacyTypes , Semantic.Api.LegacyTypes
, Semantic.Api.Symbols , Semantic.Api.Symbols
, Semantic.Api.Terms , Semantic.Api.Terms

View File

@ -54,14 +54,14 @@ isolateCache action = putCache lowerBound *> action *> ((,) <$> get <*> get)
-- | Analyze a term using the in-cache as an oracle & storing the results of the analysis in the out-cache. -- | Analyze a term using the in-cache as an oracle & storing the results of the analysis in the out-cache.
cachingTerms :: ( Member NonDet sig cachingTerms :: ( Member (Reader (Cache term address value)) sig
, Member (Reader (Cache term address value)) sig
, Member (Reader (Live address)) sig , Member (Reader (Live address)) sig
, Member (State (Cache term address value)) sig , Member (State (Cache term address value)) sig
, Carrier sig m , Carrier sig m
, Ord address , Ord address
, Ord term , Ord term
, Ord value , Ord value
, Alternative m
) )
=> Open (term -> Evaluator term address value m value) => Open (term -> Evaluator term address value m value)
cachingTerms recur term = do cachingTerms recur term = do
@ -75,7 +75,6 @@ cachingTerms recur term = do
convergingModules :: ( Eq value convergingModules :: ( Eq value
, Member Fresh sig , Member Fresh sig
, Member NonDet sig
, Member (Reader (Cache term address value)) sig , Member (Reader (Cache term address value)) sig
, Member (Reader (Live address)) sig , Member (Reader (Live address)) sig
, Member (State (Cache term address value)) sig , Member (State (Cache term address value)) sig
@ -83,9 +82,9 @@ convergingModules :: ( Eq value
, Ord address , Ord address
, Ord term , Ord term
, Carrier sig m , Carrier sig m
, Effect sig , Alternative m
) )
=> (Module (Either prelude term) -> Evaluator term address value (AltC Maybe (Eff m)) value) => (Module (Either prelude term) -> Evaluator term address value (NonDetC m) value)
-> (Module (Either prelude term) -> Evaluator term address value m value) -> (Module (Either prelude term) -> Evaluator term address value m value)
convergingModules recur m@(Module _ (Left _)) = raiseHandler runNonDet (recur m) >>= maybeM empty convergingModules recur m@(Module _ (Left _)) = raiseHandler runNonDet (recur m) >>= maybeM empty
convergingModules recur m@(Module _ (Right term)) = do convergingModules recur m@(Module _ (Right term)) = do
@ -100,7 +99,7 @@ convergingModules recur m@(Module _ (Right term)) = do
-- that it doesn't "leak" to the calling context and diverge (otherwise this -- that it doesn't "leak" to the calling context and diverge (otherwise this
-- would never complete). We dont need to use the values, so we 'gather' the -- would never complete). We dont need to use the values, so we 'gather' the
-- nondeterministic values into @()@. -- nondeterministic values into @()@.
withOracle prevCache (raiseHandler runNonDet (recur m))) withOracle prevCache (raiseHandler (runNonDet @Maybe) (recur m)))
maybe empty scatter (cacheLookup c cache) maybe empty scatter (cacheLookup c cache)
-- | Iterate a monadic action starting from some initial seed until the results converge. -- | Iterate a monadic action starting from some initial seed until the results converge.
@ -119,7 +118,7 @@ converge seed f = loop seed
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 :: (Foldable t, Member NonDet sig, Carrier sig m) => t value -> Evaluator term address value m value scatter :: (Foldable t, Carrier sig m, Alternative m) => t value -> Evaluator term address value m value
scatter = foldMapA pure scatter = foldMapA pure
-- | Get the current 'Configuration' with a passed-in term. -- | Get the current 'Configuration' with a passed-in term.
@ -129,16 +128,16 @@ getConfiguration :: (Member (Reader (Live address)) sig, Carrier sig m)
getConfiguration term = Configuration term <$> askRoots getConfiguration term = Configuration term <$> askRoots
caching :: (Carrier sig m, Effect sig) caching :: Carrier sig m
=> Evaluator term address value (AltC B (Eff => Evaluator term address value (NonDetC
(ReaderC (Cache term address value) (Eff (ReaderC (Cache term address value)
(StateC (Cache term address value) (Eff (StateC (Cache term address value)
m)))))) a m))) a
-> Evaluator term address value m (Cache term address value, [a]) -> Evaluator term address value m (Cache term address value, [a])
caching caching
= raiseHandler (runState lowerBound) = raiseHandler (runState lowerBound)
. raiseHandler (runReader lowerBound) . raiseHandler (runReader lowerBound)
. fmap toList . fmap (toList @B)
. raiseHandler runNonDet . raiseHandler runNonDet
data B a = E | L a | B (B a) (B a) data B a = E | L a | B (B a) (B a)

View File

@ -56,12 +56,12 @@ isolateCache action = putCache lowerBound *> action *> get
-- | Analyze a term using the in-cache as an oracle & storing the results of the analysis in the out-cache. -- | Analyze a term using the in-cache as an oracle & storing the results of the analysis in the out-cache.
cachingTerms :: ( Cacheable term address value cachingTerms :: ( Cacheable term address value
, Member NonDet sig
, Member (Reader (Cache term address value)) sig , Member (Reader (Cache term address value)) sig
, Member (Reader (Live address)) sig , Member (Reader (Live address)) sig
, Member (State (Cache term address value)) sig , Member (State (Cache term address value)) sig
, Member (State (Heap address address value)) sig , Member (State (Heap address address value)) sig
, Carrier sig m , Carrier sig m
, Alternative m
) )
=> Open (term -> Evaluator term address value m value) => Open (term -> Evaluator term address value m value)
cachingTerms recur term = do cachingTerms recur term = do
@ -75,15 +75,14 @@ cachingTerms recur term = do
convergingModules :: ( Cacheable term address value convergingModules :: ( Cacheable term address value
, Member Fresh sig , Member Fresh sig
, Member NonDet sig
, Member (Reader (Cache term address value)) sig , Member (Reader (Cache term address value)) sig
, Member (Reader (Live address)) sig , Member (Reader (Live address)) sig
, Member (State (Cache term address value)) sig , Member (State (Cache term address value)) sig
, Member (State (Heap address address value)) sig , Member (State (Heap address address value)) sig
, Carrier sig m , Carrier sig m
, Effect sig , Alternative m
) )
=> (Module (Either prelude term) -> Evaluator term address value (AltC Maybe (Eff m)) value) => (Module (Either prelude term) -> Evaluator term address value (NonDetC m) value)
-> (Module (Either prelude term) -> Evaluator term address value m value) -> (Module (Either prelude term) -> Evaluator term address value m value)
convergingModules recur m@(Module _ (Left _)) = raiseHandler runNonDet (recur m) >>= maybeM empty convergingModules recur m@(Module _ (Left _)) = raiseHandler runNonDet (recur m) >>= maybeM empty
convergingModules recur m@(Module _ (Right term)) = do convergingModules recur m@(Module _ (Right term)) = do
@ -98,7 +97,7 @@ convergingModules recur m@(Module _ (Right term)) = do
-- that it doesn't "leak" to the calling context and diverge (otherwise this -- that it doesn't "leak" to the calling context and diverge (otherwise this
-- would never complete). We dont need to use the values, so we 'gather' the -- would never complete). We dont need to use the values, so we 'gather' the
-- nondeterministic values into @()@. -- nondeterministic values into @()@.
withOracle prevCache (raiseHandler runNonDet (recur m))) withOracle prevCache (raiseHandler (runNonDet @Maybe) (recur m)))
maybe empty scatter (cacheLookup c cache) maybe empty scatter (cacheLookup c cache)
-- | Iterate a monadic action starting from some initial seed until the results converge. -- | Iterate a monadic action starting from some initial seed until the results converge.
@ -117,7 +116,7 @@ converge seed f = loop seed
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 :: (Foldable t, Member NonDet sig, Member (State (Heap address address value)) sig, Carrier sig m) => t (Cached address value) -> Evaluator term address value m value scatter :: (Foldable t, Member (State (Heap address address value)) sig, Alternative m, Carrier sig m) => t (Cached address value) -> Evaluator term address value m value
scatter = foldMapA (\ (Cached value heap') -> putHeap heap' $> value) scatter = foldMapA (\ (Cached value heap') -> putHeap heap' $> value)
-- | Get the current 'Configuration' with a passed-in term. -- | Get the current 'Configuration' with a passed-in term.
@ -127,11 +126,11 @@ getConfiguration :: (Member (Reader (Live address)) sig, Member (State (Heap add
getConfiguration term = Configuration term <$> askRoots <*> getHeap getConfiguration term = Configuration term <$> askRoots <*> getHeap
caching :: (Carrier sig m, Effect sig) caching :: Monad m
=> Evaluator term address value (AltC [] (Eff => Evaluator term address value ( NonDetC
(ReaderC (Cache term address value) (Eff (ReaderC (Cache term address value)
(StateC (Cache term address value) (Eff (StateC (Cache term address value)
m)))))) a m))) a
-> Evaluator term address value m (Cache term address value, [a]) -> Evaluator term address value m (Cache term address value, [a])
caching caching
= raiseHandler (runState lowerBound) = raiseHandler (runState lowerBound)

View File

@ -5,5 +5,5 @@ module Analysis.Abstract.Collecting
import Control.Abstract import Control.Abstract
import Prologue import Prologue
providingLiveSet :: Carrier sig m => Evaluator term address value (ReaderC (Live address) (Eff m)) a -> Evaluator term address value m a providingLiveSet :: Evaluator term address value (ReaderC (Live address) m) a -> Evaluator term address value m a
providingLiveSet = raiseHandler (runReader lowerBound) providingLiveSet = raiseHandler (runReader lowerBound)

View File

@ -32,20 +32,21 @@ subterms term = term `cons` para (foldMap (uncurry cons)) term
revivingTerms :: ( Member (State (Dead term)) sig revivingTerms :: ( Member (State (Dead term)) sig
, Ord term , Ord term
, Carrier sig m , Carrier sig m
) )
=> Open (term -> Evaluator term address value m a) => Open (term -> Evaluator term address value m a)
revivingTerms recur term = revive term *> recur term revivingTerms recur term = revive term *> recur term
killingModules :: ( Foldable (Base term) killingModules :: ( Foldable (Base term)
, Member (State (Dead term)) sig , Member (State (Dead term)) sig
, Ord term , Ord term
, Recursive term , Recursive term
, Carrier sig m , Carrier sig m
) )
=> Open (Module term -> Evaluator term address value m a) => Open (Module term -> Evaluator term address value m a)
killingModules recur m = killAll (subterms (moduleBody m)) *> recur m killingModules recur m = killAll (subterms (moduleBody m)) *> recur m
providingDeadSet :: (Carrier sig m, Effect sig) => Evaluator term address value (StateC (Dead term) (Evaluator term address value m)) a -> Evaluator term address value m (Dead term, a) providingDeadSet :: Evaluator term address value (StateC (Dead term) (Evaluator term address value m)) a
-> Evaluator term address value m (Dead term, a)
providingDeadSet = runState lowerBound . runEvaluator providingDeadSet = runState lowerBound . runEvaluator

View File

@ -1,4 +1,4 @@
{-# LANGUAGE LambdaCase, RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-} {-# LANGUAGE DerivingVia, LambdaCase, RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-}
module Analysis.Abstract.Graph module Analysis.Abstract.Graph
( Graph(..) ( Graph(..)
, ControlFlowVertex(..) , ControlFlowVertex(..)
@ -106,20 +106,18 @@ graphingPackages :: ( Member (Reader PackageInfo) sig
, Member (State (Graph ControlFlowVertex)) sig , Member (State (Graph ControlFlowVertex)) sig
, Member (Reader ControlFlowVertex) sig , Member (Reader ControlFlowVertex) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> Open (Module term -> m a) => Open (Module term -> m a)
graphingPackages recur m = graphingPackages recur m =
let v = moduleVertex (moduleInfo m) in packageInclusion v *> local (const v) (recur m) let v = moduleVertex (moduleInfo m) in packageInclusion v *> local (const v) (recur m)
-- | Add vertices to the graph for imported modules. -- | Add vertices to the graph for imported modules.
graphingModules :: ( Member (Modules address value) sig graphingModules :: ( Member (Reader ModuleInfo) sig
, Member (Reader ModuleInfo) sig
, Member (State (Graph ControlFlowVertex)) sig , Member (State (Graph ControlFlowVertex)) sig
, Member (Reader ControlFlowVertex) sig , Member (Reader ControlFlowVertex) sig
, Carrier sig m , Carrier sig m
) )
=> (Module body -> Evaluator term address value (EavesdropC address value (Eff m)) a) => (Module body -> Evaluator term address value (EavesdropC address value m) a)
-> (Module body -> Evaluator term address value m a) -> (Module body -> Evaluator term address value m a)
graphingModules recur m = do graphingModules recur m = do
let v = moduleVertex (moduleInfo m) let v = moduleVertex (moduleInfo m)
@ -135,12 +133,11 @@ graphingModules recur m = do
in moduleInclusion (moduleVertex (ModuleInfo path')) in moduleInclusion (moduleVertex (ModuleInfo path'))
-- | Add vertices to the graph for imported modules. -- | Add vertices to the graph for imported modules.
graphingModuleInfo :: ( Member (Modules address value) sig graphingModuleInfo :: ( Member (Reader ModuleInfo) sig
, Member (Reader ModuleInfo) sig
, Member (State (Graph ModuleInfo)) sig , Member (State (Graph ModuleInfo)) sig
, Carrier sig m , Carrier sig m
) )
=> (Module body -> Evaluator term address value (EavesdropC address value (Eff m)) a) => (Module body -> Evaluator term address value (EavesdropC address value m) a)
-> (Module body -> Evaluator term address value m a) -> (Module body -> Evaluator term address value m a)
graphingModuleInfo recur m = do graphingModuleInfo recur m = do
appendGraph (vertex (moduleInfo m)) appendGraph (vertex (moduleInfo m))
@ -149,19 +146,18 @@ graphingModuleInfo recur m = do
Lookup path _ -> currentModule >>= appendGraph . (`connect` vertex (ModuleInfo path)) . vertex Lookup path _ -> currentModule >>= appendGraph . (`connect` vertex (ModuleInfo path)) . vertex
_ -> pure () _ -> pure ()
eavesdrop :: (Carrier sig m, Member (Modules address value) sig) eavesdrop :: Evaluator term address value (EavesdropC address value m) a
=> Evaluator term address value (EavesdropC address value (Eff m)) a -> (forall x . Modules address value m (m x) -> Evaluator term address value m ())
-> (forall x . Modules address value (Eff m) (Eff m x) -> Evaluator term address value m ())
-> Evaluator term address value m a -> Evaluator term address value m a
eavesdrop m f = raiseHandler (runEavesdropC (runEvaluator . f) . interpret) m eavesdrop m f = raiseHandler (runEavesdropC (runEvaluator . f)) m
newtype EavesdropC address value m a = EavesdropC ((forall x . Modules address value m (m x) -> m ()) -> m a) newtype EavesdropC address value m a = EavesdropC ((forall x . Modules address value m (m x) -> m ()) -> m a)
deriving (Alternative, Applicative, Functor, Monad) via (ReaderC (forall x . Modules address value m (m x) -> m ()) m)
runEavesdropC :: (forall x . Modules address value m (m x) -> m ()) -> EavesdropC address value m a -> m a runEavesdropC :: (forall x . Modules address value m (m x) -> m ()) -> EavesdropC address value m a -> m a
runEavesdropC f (EavesdropC m) = m f runEavesdropC f (EavesdropC m) = m f
instance (Carrier sig m, Member (Modules address value) sig, Applicative m) => Carrier sig (EavesdropC address value m) where instance (Carrier sig m, Member (Modules address value) sig, Applicative m) => Carrier sig (EavesdropC address value m) where
ret a = EavesdropC (const (ret a))
eff op eff op
| Just eff <- prj op = EavesdropC (\ handler -> let eff' = handlePure (runEavesdropC handler) eff in handler eff' *> send eff') | Just eff <- prj op = EavesdropC (\ handler -> let eff' = handlePure (runEavesdropC handler) eff in handler eff' *> send eff')
| otherwise = EavesdropC (\ handler -> eff (handlePure (runEavesdropC handler) op)) | otherwise = EavesdropC (\ handler -> eff (handlePure (runEavesdropC handler) op))
@ -170,7 +166,6 @@ instance (Carrier sig m, Member (Modules address value) sig, Applicative m) => C
packageInclusion :: ( Member (Reader PackageInfo) sig packageInclusion :: ( Member (Reader PackageInfo) sig
, Member (State (Graph ControlFlowVertex)) sig , Member (State (Graph ControlFlowVertex)) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> ControlFlowVertex => ControlFlowVertex
-> m () -> m ()
@ -182,7 +177,6 @@ packageInclusion v = do
moduleInclusion :: ( Member (Reader ModuleInfo) sig moduleInclusion :: ( Member (Reader ModuleInfo) sig
, Member (State (Graph ControlFlowVertex)) sig , Member (State (Graph ControlFlowVertex)) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> ControlFlowVertex => ControlFlowVertex
-> m () -> m ()
@ -194,7 +188,6 @@ moduleInclusion v = do
variableDefinition :: ( Member (State (Graph ControlFlowVertex)) sig variableDefinition :: ( Member (State (Graph ControlFlowVertex)) sig
, Member (Reader ControlFlowVertex) sig , Member (Reader ControlFlowVertex) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> ControlFlowVertex => ControlFlowVertex
-> m () -> m ()
@ -202,13 +195,13 @@ variableDefinition var = do
context <- ask context <- ask
appendGraph (vertex context `connect` vertex var) appendGraph (vertex context `connect` vertex var)
appendGraph :: (Member (State (Graph v)) sig, Carrier sig m, Monad m) => Graph v -> m () appendGraph :: (Member (State (Graph v)) sig, Carrier sig m) => Graph v -> m ()
appendGraph = modify . (<>) appendGraph = modify . (<>)
graphing :: (Carrier sig m, Effect sig) graphing :: Carrier sig m
=> Evaluator term address value (StateC (Map (Slot address) ControlFlowVertex) (Eff => Evaluator term address value (StateC (Map (Slot address) ControlFlowVertex)
(StateC (Graph ControlFlowVertex) (Eff (StateC (Graph ControlFlowVertex)
m)))) result m)) result
-> Evaluator term address value m (Graph ControlFlowVertex, result) -> Evaluator term address value m (Graph ControlFlowVertex, result)
graphing = raiseHandler $ runState mempty . fmap snd . runState lowerBound graphing = raiseHandler $ runState mempty . fmap snd . runState lowerBound

View File

@ -12,18 +12,24 @@ import Data.Semigroup.Reducer as Reducer
-- --
-- Instantiating @trace@ to @[]@ yields a linear trace analysis, while @Set@ yields a reachable state analysis. -- Instantiating @trace@ to @[]@ yields a linear trace analysis, while @Set@ yields a reachable state analysis.
tracingTerms :: ( Member (State (Heap address address value)) sig tracingTerms :: ( Member (State (Heap address address value)) sig
, Member (Writer (trace (Configuration term address value))) sig , Member (Writer (trace (Configuration term address value))) sig
, Carrier sig m , Carrier sig m
, Reducer (Configuration term address value) (trace (Configuration term address value)) , Reducer (Configuration term address value) (trace (Configuration term address value))
) )
=> trace (Configuration term address value) => trace (Configuration term address value)
-> Open (term -> Evaluator term address value m a) -> Open (term -> Evaluator term address value m a)
tracingTerms proxy recur term = getConfiguration term >>= trace . (`asTypeOf` proxy) . Reducer.unit >> recur term tracingTerms proxy recur term = getConfiguration term >>= trace . (`asTypeOf` proxy) . Reducer.unit >> recur term
trace :: (Member (Writer (trace (Configuration term address value))) sig, Carrier sig m) => trace (Configuration term address value) -> Evaluator term address value m () trace :: ( Member (Writer (trace (Configuration term address value))) sig
, Carrier sig m
)
=> trace (Configuration term address value)
-> Evaluator term address value m ()
trace = tell trace = tell
tracing :: (Monoid (trace (Configuration term address value)), Carrier sig m, Effect sig) => Evaluator term address value (WriterC (trace (Configuration term address value)) (Evaluator term address value m)) a -> Evaluator term address value m (trace (Configuration term address value), a) tracing :: (Monoid (trace (Configuration term address value)))
=> Evaluator term address value (WriterC (trace (Configuration term address value)) (Evaluator term address value m)) a
-> Evaluator term address value m (trace (Configuration term address value), a)
tracing = runWriter . runEvaluator tracing = runWriter . runEvaluator

View File

@ -45,7 +45,7 @@ currentSpan = ask
withCurrentSpan :: (Member (Reader Span) sig, Carrier sig m) => Span -> m a -> m a withCurrentSpan :: (Member (Reader Span) sig, Carrier sig m) => Span -> m a -> m a
withCurrentSpan = local . const withCurrentSpan = local . const
modifyChildSpan :: (Member (State Span) sig, Carrier sig m, Monad m) => Span -> m a -> m a modifyChildSpan :: (Member (State Span) sig, Carrier sig m) => Span -> m a -> m a
modifyChildSpan span m = m <* put span modifyChildSpan span m = m <* put span
-- | Run an action with locally-replaced 'ModuleInfo' & 'Span' derived from the passed 'SrcLoc'. -- | Run an action with locally-replaced 'ModuleInfo' & 'Span' derived from the passed 'SrcLoc'.

View File

@ -29,24 +29,19 @@ import Control.Effect.Trace as X
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Data.Coerce import Data.Coerce
-- | An 'Evaluator' is a thin wrapper around 'Eff' with (phantom) type parameters for the address, term, and value types. -- | An 'Evaluator' is a thin wrapper around a monad with (phantom) type parameters for the address, term, and value types.
-- --
-- These parameters enable us to constrain the types of effects using them s.t. we can avoid both ambiguous types when they arent mentioned outside of the context, and lengthy, redundant annotations on the use sites of functions employing these effects. -- These parameters enable us to constrain the types of effects using them s.t. we can avoid both ambiguous types when they arent mentioned outside of the context, and lengthy, redundant annotations on the use sites of functions employing these effects.
-- --
-- These effects will typically include the environment, heap, module table, etc. effects necessary for evaluation of modules and terms, but may also include any other effects so long as theyre eventually handled. -- These effects will typically include the environment, heap, module table, etc. effects necessary for evaluation of modules and terms, but may also include any other effects so long as theyre eventually handled.
newtype Evaluator term address value m a = Evaluator { runEvaluator :: Eff m a } newtype Evaluator term address value m a = Evaluator { runEvaluator :: m a }
deriving (Applicative, Functor, Monad) deriving (Alternative, Applicative, Functor, Monad, MonadIO)
deriving instance (Member NonDet sig, Carrier sig m) => Alternative (Evaluator term address value m)
deriving instance (Member (Lift IO) sig, Carrier sig m) => MonadIO (Evaluator term address value m)
instance Carrier sig m => Carrier sig (Evaluator term address value m) where instance Carrier sig m => Carrier sig (Evaluator term address value m) where
ret = Evaluator . ret eff = Evaluator . eff . handleCoercible
eff = Evaluator . eff . handlePure runEvaluator
-- | Raise a handler on monads into a handler on 'Evaluator's over those monads.
-- | Raise a handler on 'Eff's into a handler on 'Evaluator's. raiseHandler :: (m a -> n b)
raiseHandler :: (Eff m a -> Eff n b)
-> Evaluator term address value m a -> Evaluator term address value m a
-> Evaluator term address value n b -> Evaluator term address value n b
raiseHandler = coerce raiseHandler = coerce
@ -69,10 +64,14 @@ earlyReturn :: ( Member (Error (Return value)) sig
-> Evaluator term address value m value -> Evaluator term address value m value
earlyReturn = throwError . Return earlyReturn = throwError . Return
catchReturn :: (Member (Error (Return value)) sig, Carrier sig m) => Evaluator term address value m value -> Evaluator term address value m value catchReturn :: (Member (Error (Return value)) sig, Carrier sig m)
=> Evaluator term address value m value
-> Evaluator term address value m value
catchReturn = flip catchError (\ (Return value) -> pure value) catchReturn = flip catchError (\ (Return value) -> pure value)
runReturn :: (Carrier sig m, Effect sig) => Evaluator term address value (ErrorC (Return value) (Eff m)) value -> Evaluator term address value m value runReturn :: Carrier sig m
=> Evaluator term address value (ErrorC (Return value) m) value
-> Evaluator term address value m value
runReturn = raiseHandler $ fmap (either unReturn id) . runError runReturn = raiseHandler $ fmap (either unReturn id) . runError
@ -105,7 +104,7 @@ catchLoopControl :: ( Member (Error (LoopControl value)) sig
-> Evaluator term address value m a -> Evaluator term address value m a
catchLoopControl = catchError catchLoopControl = catchError
runLoopControl :: (Carrier sig m, Effect sig) runLoopControl :: Carrier sig m
=> Evaluator term address value (ErrorC (LoopControl value) (Eff m)) value => Evaluator term address value (ErrorC (LoopControl value) m) value
-> Evaluator term address value m value -> Evaluator term address value m value
runLoopControl = raiseHandler $ fmap (either unLoopControl id) . runError runLoopControl = raiseHandler $ fmap (either unLoopControl id) . runError

View File

@ -222,7 +222,7 @@ deref :: ( Member (Deref value) sig
deref slot@Slot{..} = do deref slot@Slot{..} = do
maybeSlotValue <- gets (Heap.getSlotValue slot) maybeSlotValue <- gets (Heap.getSlotValue slot)
slotValue <- maybeM (throwAddressError (UnallocatedSlot slot)) maybeSlotValue slotValue <- maybeM (throwAddressError (UnallocatedSlot slot)) maybeSlotValue
eff <- send $ DerefCell slotValue ret eff <- send $ DerefCell slotValue pure
maybeM (throwAddressError $ UninitializedSlot slot) eff maybeM (throwAddressError $ UninitializedSlot slot) eff
putSlotDeclarationScope :: ( Member (State (Heap address address value)) sig putSlotDeclarationScope :: ( Member (State (Heap address address value)) sig
@ -375,7 +375,7 @@ assign :: ( Member (Deref value) sig
-> Evaluator term address value m () -> Evaluator term address value m ()
assign addr value = do assign addr value = do
heap <- getHeap heap <- getHeap
cell <- send (AssignCell value (fromMaybe lowerBound (Heap.getSlotValue addr heap)) ret) cell <- send (AssignCell value (fromMaybe lowerBound (Heap.getSlotValue addr heap)) pure)
putHeap (Heap.setSlot addr cell heap) putHeap (Heap.setSlot addr cell heap)
dealloc :: ( Carrier sig m dealloc :: ( Carrier sig m
@ -431,10 +431,9 @@ instance Effect (Deref value) where
handle state handler (DerefCell cell k) = DerefCell cell (handler . (<$ state) . k) handle state handler (DerefCell cell k) = DerefCell cell (handler . (<$ state) . k)
handle state handler (AssignCell value cell k) = AssignCell value cell (handler . (<$ state) . k) handle state handler (AssignCell value cell k) = AssignCell value cell (handler . (<$ state) . k)
runDeref :: Carrier (Deref value :+: sig) (DerefC address value (Eff m)) runDeref :: Evaluator term address value (DerefC address value m) a
=> Evaluator term address value (DerefC address value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runDeref = raiseHandler $ runDerefC . interpret runDeref = raiseHandler runDerefC
newtype DerefC address value m a = DerefC { runDerefC :: m a } newtype DerefC address value m a = DerefC { runDerefC :: m a }
deriving (Alternative, Applicative, Functor, Monad) deriving (Alternative, Applicative, Functor, Monad)
@ -481,14 +480,12 @@ throwHeapError :: ( Member (Resumable (BaseError (HeapError address))) sig
-> Evaluator term address value m resume -> Evaluator term address value m resume
throwHeapError = throwBaseError throwHeapError = throwBaseError
runHeapError :: (Carrier sig m, Effect sig) runHeapError :: Evaluator term address value (ResumableC (BaseError (HeapError address)) m) a
=> Evaluator term address value (ResumableC (BaseError (HeapError address)) (Eff m)) a -> Evaluator term address value m (Either (SomeError (BaseError (HeapError address))) a)
-> Evaluator term address value m (Either (SomeError (BaseError (HeapError address))) a)
runHeapError = raiseHandler runResumable runHeapError = raiseHandler runResumable
runHeapErrorWith :: Carrier sig m runHeapErrorWith :: (forall resume. (BaseError (HeapError address)) resume -> Evaluator term address value m resume)
=> (forall resume. (BaseError (HeapError address)) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError (HeapError address)) m) a
-> Evaluator term address value (ResumableWithC (BaseError (HeapError address)) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runHeapErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runHeapErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)
@ -522,13 +519,11 @@ throwAddressError :: ( Member (Resumable (BaseError (AddressError address body))
-> Evaluator term address value m resume -> Evaluator term address value m resume
throwAddressError = throwBaseError throwAddressError = throwBaseError
runAddressError :: (Carrier sig m, Effect sig) runAddressError :: Evaluator term address value (ResumableC (BaseError (AddressError address value)) m) a
=> Evaluator term address value (ResumableC (BaseError (AddressError address value)) (Eff m)) a
-> Evaluator term address value m (Either (SomeError (BaseError (AddressError address value))) a) -> Evaluator term address value m (Either (SomeError (BaseError (AddressError address value))) a)
runAddressError = raiseHandler runResumable runAddressError = raiseHandler runResumable
runAddressErrorWith :: Carrier sig m runAddressErrorWith :: (forall resume . (BaseError (AddressError address value)) resume -> Evaluator term address value m resume)
=> (forall resume . (BaseError (AddressError address value)) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError (AddressError address value)) m) a
-> Evaluator term address value (ResumableWithC (BaseError (AddressError address value)) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runAddressErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runAddressErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE GADTs, LambdaCase, KindSignatures, RankNTypes, ScopedTypeVariables, TypeOperators, UndecidableInstances #-} {-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, KindSignatures, RankNTypes, ScopedTypeVariables, TypeOperators, UndecidableInstances #-}
module Control.Abstract.Modules module Control.Abstract.Modules
( ModuleResult ( ModuleResult
, lookupModule , lookupModule
@ -36,14 +36,14 @@ type ModuleResult address value = ((address, address), value)
-- | Retrieve an evaluated module, if any. @Nothing@ means weve never tried to load it, and @Just (env, value)@ indicates the result of a completed load. -- | Retrieve an evaluated module, if any. @Nothing@ means weve never tried to load it, and @Just (env, value)@ indicates the result of a completed load.
lookupModule :: (Member (Modules address value) sig, Carrier sig m) => ModulePath -> Evaluator term address value m (Maybe (ModuleResult address value)) lookupModule :: (Member (Modules address value) sig, Carrier sig m) => ModulePath -> Evaluator term address value m (Maybe (ModuleResult address value))
lookupModule = sendModules . flip Lookup ret lookupModule = sendModules . flip Lookup pure
-- | Resolve a list of module paths to a possible module table entry. -- | Resolve a list of module paths to a possible module table entry.
resolve :: (Member (Modules address value) sig, Carrier sig m) => [FilePath] -> Evaluator term address value m (Maybe ModulePath) resolve :: (Member (Modules address value) sig, Carrier sig m) => [FilePath] -> Evaluator term address value m (Maybe ModulePath)
resolve = sendModules . flip Resolve ret resolve = sendModules . flip Resolve pure
listModulesInDir :: (Member (Modules address value) sig, Carrier sig m) => FilePath -> Evaluator term address value m [ModulePath] listModulesInDir :: (Member (Modules address value) sig, Carrier sig m) => FilePath -> Evaluator term address value m [ModulePath]
listModulesInDir = sendModules . flip List ret listModulesInDir = sendModules . flip List pure
-- | Require/import another module by name and return its environment and value. -- | Require/import another module by name and return its environment and value.
@ -56,7 +56,7 @@ require path = lookupModule path >>= maybeM (load path)
-- --
-- Always loads/evaluates. -- Always loads/evaluates.
load :: (Member (Modules address value) sig, Carrier sig m) => ModulePath -> Evaluator term address value m (ModuleResult address value) load :: (Member (Modules address value) sig, Carrier sig m) => ModulePath -> Evaluator term address value m (ModuleResult address value)
load path = sendModules (Load path ret) load path = sendModules (Load path pure)
data Modules address value (m :: * -> *) k data Modules address value (m :: * -> *) k
@ -82,29 +82,27 @@ sendModules :: ( Member (Modules address value) sig
-> Evaluator term address value m return -> Evaluator term address value m return
sendModules = send sendModules = send
runModules :: ( Member (Reader (ModuleTable (Module (ModuleResult address value)))) sig runModules :: Set ModulePath
, Member (Resumable (BaseError (LoadError address value))) sig -> Evaluator term address value (ModulesC address value m) a
, Carrier sig m
)
=> Set ModulePath
-> Evaluator term address value (ModulesC address value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runModules paths = raiseHandler $ flip runModulesC paths . interpret runModules paths = raiseHandler (runReader paths . runModulesC)
newtype ModulesC address value m a = ModulesC { runModulesC :: Set ModulePath -> m a } newtype ModulesC address value m a = ModulesC { runModulesC :: ReaderC (Set ModulePath) m a }
deriving (Alternative, Applicative, Functor, Monad, MonadIO)
instance ( Member (Reader (ModuleTable (Module (ModuleResult address value)))) sig instance ( Member (Reader (ModuleTable (Module (ModuleResult address value)))) sig
, Member (Resumable (BaseError (LoadError address value))) sig , Member (Resumable (BaseError (LoadError address value))) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> Carrier (Modules address value :+: sig) (ModulesC address value m) where => Carrier (Modules address value :+: sig) (ModulesC address value m) where
ret = ModulesC . const . ret eff (L op) = do
eff op = ModulesC (\ paths -> handleSum (eff . handleReader paths runModulesC) (\case paths <- ModulesC ask
Load name k -> askModuleTable >>= maybeM (throwLoadError (ModuleNotFoundError name)) . fmap moduleBody . ModuleTable.lookup name >>= flip runModulesC paths . k case op of
Lookup path k -> askModuleTable >>= flip runModulesC paths . k . fmap moduleBody . ModuleTable.lookup path Load name k -> askModuleTable >>= maybeM (throwLoadError (ModuleNotFoundError name)) . fmap moduleBody . ModuleTable.lookup name >>= k
Resolve names k -> runModulesC (k (find (`Set.member` paths) names)) paths Lookup path k -> askModuleTable >>= k . fmap moduleBody . ModuleTable.lookup path
List dir k -> runModulesC (k (filter ((dir ==) . takeDirectory) (toList paths))) paths) op) Resolve names k -> k (find (`Set.member` paths) names)
List dir k -> k (filter ((dir ==) . takeDirectory) (toList paths))
eff (R other) = ModulesC (eff (R (handleCoercible other)))
askModuleTable :: (Member (Reader (ModuleTable (Module (ModuleResult address value)))) sig, Carrier sig m) => m (ModuleTable (Module (ModuleResult address value))) askModuleTable :: (Member (Reader (ModuleTable (Module (ModuleResult address value)))) sig, Carrier sig m) => m (ModuleTable (Module (ModuleResult address value)))
askModuleTable = ask askModuleTable = ask
@ -124,14 +122,12 @@ instance Eq1 (LoadError address value) where
instance NFData1 (LoadError address value) where instance NFData1 (LoadError address value) where
liftRnf _ (ModuleNotFoundError p) = rnf p liftRnf _ (ModuleNotFoundError p) = rnf p
runLoadError :: (Carrier sig m, Effect sig) runLoadError :: Evaluator term address value (ResumableC (BaseError (LoadError address value)) m) a
=> Evaluator term address value (ResumableC (BaseError (LoadError address value)) (Eff m)) a
-> Evaluator term address value m (Either (SomeError (BaseError (LoadError address value))) a) -> Evaluator term address value m (Either (SomeError (BaseError (LoadError address value))) a)
runLoadError = raiseHandler runResumable runLoadError = raiseHandler runResumable
runLoadErrorWith :: Carrier sig m runLoadErrorWith :: (forall resume . (BaseError (LoadError address value)) resume -> Evaluator term address value m resume)
=> (forall resume . (BaseError (LoadError address value)) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError (LoadError address value)) m) a
-> Evaluator term address value (ResumableWithC (BaseError (LoadError address value)) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runLoadErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runLoadErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)
@ -162,14 +158,12 @@ instance NFData1 ResolutionError where
NotFoundError p ps l -> rnf p `seq` rnf ps `seq` rnf l NotFoundError p ps l -> rnf p `seq` rnf ps `seq` rnf l
GoImportError p -> rnf p GoImportError p -> rnf p
runResolutionError :: (Carrier sig m, Effect sig) runResolutionError :: Evaluator term address value (ResumableC (BaseError ResolutionError) m) a
=> Evaluator term address value (ResumableC (BaseError ResolutionError) (Eff m)) a
-> Evaluator term address value m (Either (SomeError (BaseError ResolutionError)) a) -> Evaluator term address value m (Either (SomeError (BaseError ResolutionError)) a)
runResolutionError = raiseHandler runResumable runResolutionError = raiseHandler runResumable
runResolutionErrorWith :: Carrier sig m runResolutionErrorWith :: (forall resume . (BaseError ResolutionError) resume -> Evaluator term address value m resume)
=> (forall resume . (BaseError ResolutionError) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError ResolutionError) m) a
-> Evaluator term address value (ResumableWithC (BaseError ResolutionError) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runResolutionErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runResolutionErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving, UndecidableInstances #-}
module Control.Abstract.PythonPackage module Control.Abstract.PythonPackage
( runPythonPackaging, Strategy(..) ) where ( runPythonPackaging, Strategy(..) ) where
@ -14,19 +14,15 @@ import Prologue
data Strategy = Unknown | Packages [Text] | FindPackages [Text] data Strategy = Unknown | Packages [Text] | FindPackages [Text]
deriving (Show, Eq) deriving (Show, Eq)
runPythonPackaging :: ( Carrier sig m runPythonPackaging :: Evaluator term address (Value term address) (PythonPackagingC term address m) a
, Member (Abstract.String (Value term address)) sig
, Member (Abstract.Array (Value term address)) sig
, Member (State Strategy) sig
, Member (Function term address (Value term address)) sig)
=> Evaluator term address (Value term address) (PythonPackagingC term address (Eff m)) a
-> Evaluator term address (Value term address) m a -> Evaluator term address (Value term address) m a
runPythonPackaging = raiseHandler (runPythonPackagingC . interpret) runPythonPackaging = raiseHandler runPythonPackagingC
newtype PythonPackagingC term address m a = PythonPackagingC { runPythonPackagingC :: m a } newtype PythonPackagingC term address m a = PythonPackagingC { runPythonPackagingC :: m a }
deriving (Applicative, Functor, Monad)
wrap :: Evaluator term address (Value term address) m a -> PythonPackagingC term address (Eff m) a wrap :: Evaluator term address (Value term address) m a -> PythonPackagingC term address m a
wrap = PythonPackagingC . runEvaluator wrap = PythonPackagingC . runEvaluator
instance ( Carrier sig m instance ( Carrier sig m
@ -35,8 +31,7 @@ instance ( Carrier sig m
, Member (Abstract.String (Value term address)) sig , Member (Abstract.String (Value term address)) sig
, Member (Abstract.Array (Value term address)) sig , Member (Abstract.Array (Value term address)) sig
) )
=> Carrier sig (PythonPackagingC term address (Eff m)) where => Carrier sig (PythonPackagingC term address m) where
ret = PythonPackagingC . ret
eff op eff op
| Just e <- prj op = wrap $ case handleCoercible e of | Just e <- prj op = wrap $ case handleCoercible e of
Call callName params k -> Evaluator . k =<< do Call callName params k -> Evaluator . k =<< do
@ -61,4 +56,4 @@ instance ( Carrier sig m
Function name params body scope k -> function name params body scope >>= Evaluator . k Function name params body scope k -> function name params body scope >>= Evaluator . k
BuiltIn n b k -> builtIn n b >>= Evaluator . k BuiltIn n b k -> builtIn n b >>= Evaluator . k
Bind obj value k -> bindThis obj value >>= Evaluator . k Bind obj value k -> bindThis obj value >>= Evaluator . k
| otherwise = PythonPackagingC (eff (handleCoercible op)) | otherwise = PythonPackagingC . eff $ handleCoercible op

View File

@ -355,7 +355,7 @@ instance NFData return => NFData (ScopeError address return) where
rnf = liftRnf rnf rnf = liftRnf rnf
alloc :: (Member (Allocator address) sig, Carrier sig m) => Name -> Evaluator term address value m address alloc :: (Member (Allocator address) sig, Carrier sig m) => Name -> Evaluator term address value m address
alloc = send . flip Alloc ret alloc = send . flip Alloc pure
data Allocator address (m :: * -> *) k data Allocator address (m :: * -> *) k
= Alloc Name (address -> k) = Alloc Name (address -> k)
@ -367,22 +367,18 @@ instance HFunctor (Allocator address) where
instance Effect (Allocator address) where instance Effect (Allocator address) where
handle state handler (Alloc name k) = Alloc name (handler . (<$ state) . k) handle state handler (Alloc name k) = Alloc name (handler . (<$ state) . k)
runAllocator :: Carrier (Allocator address :+: sig) (AllocatorC address (Eff m)) runAllocator :: Evaluator term address value (AllocatorC address m) a
=> Evaluator term address value (AllocatorC address (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runAllocator = raiseHandler $ runAllocatorC . interpret runAllocator = raiseHandler runAllocatorC
newtype AllocatorC address m a = AllocatorC { runAllocatorC :: m a } newtype AllocatorC address m a = AllocatorC { runAllocatorC :: m a }
deriving (Alternative, Applicative, Functor, Monad) deriving (Alternative, Applicative, Functor, Monad)
runScopeErrorWith :: (forall resume . BaseError (ScopeError address) resume -> Evaluator term address value m resume)
runScopeErrorWith :: Carrier sig m -> Evaluator term address value (ResumableWithC (BaseError (ScopeError address)) m) a
=> (forall resume . BaseError (ScopeError address) resume -> Evaluator term address value m resume)
-> Evaluator term address value (ResumableWithC (BaseError (ScopeError address)) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runScopeErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runScopeErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)
runScopeError :: (Carrier sig m, Effect sig) runScopeError :: Evaluator term address value (ResumableC (BaseError (ScopeError address)) m) a
=> Evaluator term address value (ResumableC (BaseError (ScopeError address)) (Eff m)) a
-> Evaluator term address value m (Either (SomeError (BaseError (ScopeError address))) a) -> Evaluator term address value m (Either (SomeError (BaseError (ScopeError address))) a)
runScopeError = raiseHandler runResumable runScopeError = raiseHandler runResumable

View File

@ -1,4 +1,4 @@
{-# LANGUAGE DeriveAnyClass, GADTs, KindSignatures, LambdaCase, Rank2Types, ScopedTypeVariables, TypeOperators #-} {-# LANGUAGE DeriveAnyClass, DerivingStrategies, GADTs, GeneralizedNewtypeDeriving, KindSignatures, LambdaCase, Rank2Types, ScopedTypeVariables, TypeOperators #-}
module Control.Abstract.Value module Control.Abstract.Value
( AbstractValue(..) ( AbstractValue(..)
, AbstractIntro(..) , AbstractIntro(..)
@ -105,7 +105,7 @@ data Comparator
-- In the concrete domain, introductions & eliminations respectively construct & pattern match against values, while in abstract domains they respectively construct & project finite sets of discrete observations of abstract values. For example, an abstract domain modelling integers as a sign (-, 0, or +) would introduce abstract values by mapping integers to their sign and eliminate them by mapping signs back to some canonical integer, e.g. - -> -1, 0 -> 0, + -> 1. -- In the concrete domain, introductions & eliminations respectively construct & pattern match against values, while in abstract domains they respectively construct & project finite sets of discrete observations of abstract values. For example, an abstract domain modelling integers as a sign (-, 0, or +) would introduce abstract values by mapping integers to their sign and eliminate them by mapping signs back to some canonical integer, e.g. - -> -1, 0 -> 0, + -> 1.
function :: (Member (Function term address value) sig, Carrier sig m) => Name -> [Name] -> term -> address -> Evaluator term address value m value function :: (Member (Function term address value) sig, Carrier sig m) => Name -> [Name] -> term -> address -> Evaluator term address value m value
function name params body scope = sendFunction (Function name params body scope ret) function name params body scope = sendFunction (Function name params body scope pure)
data BuiltIn data BuiltIn
= Print = Print
@ -113,16 +113,16 @@ data BuiltIn
deriving (Eq, Ord, Show, Generic, NFData) deriving (Eq, Ord, Show, Generic, NFData)
builtIn :: (Member (Function term address value) sig, Carrier sig m) => address -> BuiltIn -> Evaluator term address value m value builtIn :: (Member (Function term address value) sig, Carrier sig m) => address -> BuiltIn -> Evaluator term address value m value
builtIn address = sendFunction . flip (BuiltIn address) ret builtIn address = sendFunction . flip (BuiltIn address) pure
call :: (Member (Function term address value) sig, Carrier sig m) => value -> [value] -> Evaluator term address value m value call :: (Member (Function term address value) sig, Carrier sig m) => value -> [value] -> Evaluator term address value m value
call fn args = sendFunction (Call fn args ret) call fn args = sendFunction (Call fn args pure)
sendFunction :: (Member (Function term address value) sig, Carrier sig m) => Function term address value (Evaluator term address value m) (Evaluator term address value m a) -> Evaluator term address value m a sendFunction :: (Member (Function term address value) sig, Carrier sig m) => Function term address value (Evaluator term address value m) (Evaluator term address value m a) -> Evaluator term address value m a
sendFunction = send sendFunction = send
bindThis :: (Member (Function term address value) sig, Carrier sig m) => value -> value -> Evaluator term address value m value bindThis :: (Member (Function term address value) sig, Carrier sig m) => value -> value -> Evaluator term address value m value
bindThis this that = sendFunction (Bind this that ret) bindThis this that = sendFunction (Bind this that pure)
data Function term address value (m :: * -> *) k data Function term address value (m :: * -> *) k
= Function Name [Name] term address (value -> k) -- ^ A function is parameterized by its name, parameter names, body, parent scope, and returns a ValueRef. = Function Name [Name] term address (value -> k) -- ^ A function is parameterized by its name, parameter names, body, parent scope, and returns a ValueRef.
@ -138,25 +138,24 @@ instance Effect (Function term address value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
runFunction :: Carrier (Function term address value :+: sig) (FunctionC term address value (Eff m)) runFunction :: (term -> Evaluator term address value (FunctionC term address value m) value)
=> (term -> Evaluator term address value (FunctionC term address value (Eff m)) value) -> Evaluator term address value (FunctionC term address value m) a
-> Evaluator term address value (FunctionC term address value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runFunction eval = raiseHandler (flip runFunctionC (runEvaluator . eval) . interpret) runFunction eval = raiseHandler (runReader (runEvaluator . eval) . runFunctionC)
newtype FunctionC term address value m a = FunctionC { runFunctionC :: (term -> Eff (FunctionC term address value m) value) -> m a }
newtype FunctionC term address value m a = FunctionC { runFunctionC :: ReaderC (term -> FunctionC term address value m value) m a }
deriving newtype (Alternative, Applicative, Functor, Monad)
-- | Construct a boolean value in the abstract domain. -- | Construct a boolean value in the abstract domain.
boolean :: (Member (Boolean value) sig, Carrier sig m) => Bool -> m value boolean :: (Member (Boolean value) sig, Carrier sig m) => Bool -> m value
boolean = send . flip Boolean ret boolean = send . flip Boolean pure
-- | Extract a 'Bool' from a given value. -- | Extract a 'Bool' from a given value.
asBool :: (Member (Boolean value) sig, Carrier sig m) => value -> m Bool asBool :: (Member (Boolean value) sig, Carrier sig m) => value -> m Bool
asBool = send . flip AsBool ret asBool = send . flip AsBool pure
-- | Eliminate boolean values. TODO: s/boolean/truthy -- | Eliminate boolean values. TODO: s/boolean/truthy
ifthenelse :: (Member (Boolean value) sig, Carrier sig m, Monad m) => value -> m a -> m a -> m a ifthenelse :: (Member (Boolean value) sig, Carrier sig m) => value -> m a -> m a -> m a
ifthenelse v t e = asBool v >>= \ c -> if c then t else e ifthenelse v t e = asBool v >>= \ c -> if c then t else e
data Boolean value (m :: * -> *) k data Boolean value (m :: * -> *) k
@ -173,12 +172,13 @@ instance Effect (Boolean value) where
Boolean b k -> Boolean b (handler . (<$ state) . k) Boolean b k -> Boolean b (handler . (<$ state) . k)
AsBool v k -> AsBool v (handler . (<$ state) . k) AsBool v k -> AsBool v (handler . (<$ state) . k)
runBoolean :: Carrier (Boolean value :+: sig) (BooleanC value (Eff m)) runBoolean :: Evaluator term address value (BooleanC value m) a
=> Evaluator term address value (BooleanC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runBoolean = raiseHandler $ runBooleanC . interpret runBoolean = raiseHandler runBooleanC
newtype BooleanC value m a = BooleanC { runBooleanC :: m a } newtype BooleanC value m a = BooleanC { runBooleanC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
-- | The fundamental looping primitive, built on top of 'ifthenelse'. -- | The fundamental looping primitive, built on top of 'ifthenelse'.
@ -186,7 +186,7 @@ while :: (Member (While value) sig, Carrier sig m)
=> Evaluator term address value m value -- ^ Condition => Evaluator term address value m value -- ^ Condition
-> Evaluator term address value m value -- ^ Body -> Evaluator term address value m value -- ^ Body
-> Evaluator term address value m value -> Evaluator term address value m value
while cond body = send (While cond body ret) while cond body = send (While cond body pure)
-- | Do-while loop, built on top of while. -- | Do-while loop, built on top of while.
doWhile :: (Member (While value) sig, Carrier sig m) doWhile :: (Member (While value) sig, Carrier sig m)
@ -223,21 +223,21 @@ data While value m k
instance HFunctor (While value) where instance HFunctor (While value) where
hmap f (While cond body k) = While (f cond) (f body) k hmap f (While cond body k) = While (f cond) (f body) k
runWhile :: Carrier (While value :+: sig) (WhileC value (Eff m)) runWhile :: Evaluator term address value (WhileC value m) a
=> Evaluator term address value (WhileC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runWhile = raiseHandler $ runWhileC . interpret runWhile = raiseHandler runWhileC
newtype WhileC value m a = WhileC { runWhileC :: m a } newtype WhileC value m a = WhileC { runWhileC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
-- | Construct an abstract unit value. -- | Construct an abstract unit value.
unit :: (Carrier sig m, Member (Unit value) sig) => Evaluator term address value m value unit :: (Carrier sig m, Member (Unit value) sig) => Evaluator term address value m value
unit = send (Unit ret) unit = send (Unit pure)
newtype Unit value (m :: * -> *) k newtype Unit value (m :: * -> *) k
= Unit (value -> k) = Unit (value -> k)
deriving (Functor) deriving stock Functor
instance HFunctor (Unit value) where instance HFunctor (Unit value) where
hmap _ = coerce hmap _ = coerce
@ -246,21 +246,21 @@ instance HFunctor (Unit value) where
instance Effect (Unit value) where instance Effect (Unit value) where
handle state handler (Unit k) = Unit (handler . (<$ state) . k) handle state handler (Unit k) = Unit (handler . (<$ state) . k)
runUnit :: Carrier (Unit value :+: sig) (UnitC value (Eff m)) runUnit :: Evaluator term address value (UnitC value m) a
=> Evaluator term address value (UnitC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runUnit = raiseHandler $ runUnitC . interpret runUnit = raiseHandler runUnitC
newtype UnitC value m a = UnitC { runUnitC :: m a } newtype UnitC value m a = UnitC { runUnitC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
-- | Construct a String value in the abstract domain. -- | Construct a String value in the abstract domain.
string :: (Member (String value) sig, Carrier sig m) => Text -> m value string :: (Member (String value) sig, Carrier sig m) => Text -> m value
string t = send (String t ret) string t = send (String t pure)
-- | Extract 'Text' from a given value. -- | Extract 'Text' from a given value.
asString :: (Member (String value) sig, Carrier sig m) => value -> m Text asString :: (Member (String value) sig, Carrier sig m) => value -> m Text
asString v = send (AsString v ret) asString v = send (AsString v pure)
data String value (m :: * -> *) k data String value (m :: * -> *) k
= String Text (value -> k) = String Text (value -> k)
@ -276,31 +276,32 @@ instance Effect (String value) where
handle state handler (AsString v k) = AsString v (handler . (<$ state) . k) handle state handler (AsString v k) = AsString v (handler . (<$ state) . k)
newtype StringC value m a = StringC { runStringC :: m a } newtype StringC value m a = StringC { runStringC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
runString :: Carrier (String value :+: sig) (StringC value (Eff m)) runString :: Evaluator term address value (StringC value m) a
=> Evaluator term address value (StringC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runString = raiseHandler $ runStringC . interpret runString = raiseHandler runStringC
-- | Construct an abstract integral value. -- | Construct an abstract integral value.
integer :: (Member (Numeric value) sig, Carrier sig m) => Integer -> m value integer :: (Member (Numeric value) sig, Carrier sig m) => Integer -> m value
integer t = send (Integer t ret) integer t = send (Integer t pure)
-- | Construct a floating-point value. -- | Construct a floating-point value.
float :: (Member (Numeric value) sig, Carrier sig m) => Scientific -> m value float :: (Member (Numeric value) sig, Carrier sig m) => Scientific -> m value
float t = send (Float t ret) float t = send (Float t pure)
-- | Construct a rational value. -- | Construct a rational value.
rational :: (Member (Numeric value) sig, Carrier sig m) => Rational -> m value rational :: (Member (Numeric value) sig, Carrier sig m) => Rational -> m value
rational t = send (Rational t ret) rational t = send (Rational t pure)
-- | Lift a unary operator over a 'Num' to a function on 'value's. -- | Lift a unary operator over a 'Num' to a function on 'value's.
liftNumeric :: (Member (Numeric value) sig, Carrier sig m) liftNumeric :: (Member (Numeric value) sig, Carrier sig m)
=> (forall a . Num a => a -> a) => (forall a . Num a => a -> a)
-> value -> value
-> m value -> m value
liftNumeric t v = send (LiftNumeric t v ret) liftNumeric t v = send (LiftNumeric t v pure)
-- | Lift a pair of binary operators to a function on 'value's. -- | Lift a pair of binary operators to a function on 'value's.
-- You usually pass the same operator as both arguments, except in the cases where -- You usually pass the same operator as both arguments, except in the cases where
@ -311,7 +312,7 @@ liftNumeric2 :: (Member (Numeric value) sig, Carrier sig m)
-> value -> value
-> value -> value
-> m value -> m value
liftNumeric2 t v1 v2 = send (LiftNumeric2 t v1 v2 ret) liftNumeric2 t v1 v2 = send (LiftNumeric2 t v1 v2 pure)
data Numeric value (m :: * -> *) k data Numeric value (m :: * -> *) k
= Integer Integer (value -> k) = Integer Integer (value -> k)
@ -329,23 +330,24 @@ instance Effect (Numeric value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
newtype NumericC value m a = NumericC { runNumericC :: m a } newtype NumericC value m a = NumericC { runNumericC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
runNumeric :: Carrier (Numeric value :+: sig) (NumericC value (Eff m)) runNumeric :: Evaluator term address value (NumericC value m) a
=> Evaluator term address value (NumericC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runNumeric = raiseHandler $ runNumericC . interpret runNumeric = raiseHandler runNumericC
-- | Cast numbers to integers -- | Cast numbers to integers
castToInteger :: (Member (Bitwise value) sig, Carrier sig m) => value -> m value castToInteger :: (Member (Bitwise value) sig, Carrier sig m) => value -> m value
castToInteger t = send (CastToInteger t ret) castToInteger t = send (CastToInteger t pure)
-- | Lift a unary bitwise operator to values. This is usually 'complement'. -- | Lift a unary bitwise operator to values. This is usually 'complement'.
liftBitwise :: (Member (Bitwise value) sig, Carrier sig m) liftBitwise :: (Member (Bitwise value) sig, Carrier sig m)
=> (forall a . Bits a => a -> a) => (forall a . Bits a => a -> a)
-> value -> value
-> m value -> m value
liftBitwise t v = send (LiftBitwise t v ret) liftBitwise t v = send (LiftBitwise t v pure)
-- | Lift a binary bitwise operator to values. The Integral constraint is -- | Lift a binary bitwise operator to values. The Integral constraint is
-- necessary to satisfy implementation details of Haskell left/right shift, -- necessary to satisfy implementation details of Haskell left/right shift,
@ -355,13 +357,13 @@ liftBitwise2 :: (Member (Bitwise value) sig, Carrier sig m)
-> value -> value
-> value -> value
-> m value -> m value
liftBitwise2 t v1 v2 = send (LiftBitwise2 t v1 v2 ret) liftBitwise2 t v1 v2 = send (LiftBitwise2 t v1 v2 pure)
unsignedRShift :: (Member (Bitwise value) sig, Carrier sig m) unsignedRShift :: (Member (Bitwise value) sig, Carrier sig m)
=> value => value
-> value -> value
-> m value -> m value
unsignedRShift v1 v2 = send (UnsignedRShift v1 v2 ret) unsignedRShift v1 v2 = send (UnsignedRShift v1 v2 pure)
data Bitwise value (m :: * -> *) k data Bitwise value (m :: * -> *) k
= CastToInteger value (value -> k) = CastToInteger value (value -> k)
@ -377,26 +379,26 @@ instance HFunctor (Bitwise value) where
instance Effect (Bitwise value) where instance Effect (Bitwise value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
runBitwise :: Carrier (Bitwise value :+: sig) (BitwiseC value (Eff m)) runBitwise :: Evaluator term address value (BitwiseC value m) a
=> Evaluator term address value (BitwiseC value (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runBitwise = raiseHandler $ runBitwiseC . interpret runBitwise = raiseHandler runBitwiseC
newtype BitwiseC value m a = BitwiseC { runBitwiseC :: m a } newtype BitwiseC value m a = BitwiseC { runBitwiseC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
object :: (Member (Object address value) sig, Carrier sig m) => address -> m value object :: (Member (Object address value) sig, Carrier sig m) => address -> m value
object address = send (Object address ret) object address = send (Object address pure)
-- | Extract the environment from any scoped object (e.g. classes, namespaces, etc). -- | Extract the environment from any scoped object (e.g. classes, namespaces, etc).
scopedEnvironment :: (Member (Object address value) sig, Carrier sig m) => value -> m (Maybe address) scopedEnvironment :: (Member (Object address value) sig, Carrier sig m) => value -> m (Maybe address)
scopedEnvironment value = send (ScopedEnvironment value ret) scopedEnvironment value = send (ScopedEnvironment value pure)
-- | Build a class value from a name and environment. -- | Build a class value from a name and environment.
-- declaration is the new class's identifier -- declaration is the new class's identifier
-- address is the environment to capture -- address is the environment to capture
klass :: (Member (Object address value) sig, Carrier sig m) => Declaration -> address -> m value klass :: (Member (Object address value) sig, Carrier sig m) => Declaration -> address -> m value
klass d a = send (Klass d a ret) klass d a = send (Klass d a pure)
data Object address value (m :: * -> *) k data Object address value (m :: * -> *) k
= Object address (value -> k) = Object address (value -> k)
@ -412,18 +414,19 @@ instance Effect (Object address value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
newtype ObjectC address value m a = ObjectC { runObjectC :: m a } newtype ObjectC address value m a = ObjectC { runObjectC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
runObject :: Carrier (Object address value :+: sig) (ObjectC address value (Eff m)) runObject :: Evaluator term address value (ObjectC address value m) a
=> Evaluator term address value (ObjectC address value (Eff m)) a -> Evaluator term address value m a
-> Evaluator term address value m a runObject = raiseHandler runObjectC
runObject = raiseHandler $ runObjectC . interpret
-- | Construct an array of zero or more values. -- | Construct an array of zero or more values.
array :: (Member (Array value) sig, Carrier sig m) => [value] -> m value array :: (Member (Array value) sig, Carrier sig m) => [value] -> m value
array v = send (Array v ret) array v = send (Array v pure)
asArray :: (Member (Array value) sig, Carrier sig m) => value -> m [value] asArray :: (Member (Array value) sig, Carrier sig m) => value -> m [value]
asArray v = send (AsArray v ret) asArray v = send (AsArray v pure)
data Array value (m :: * -> *) k data Array value (m :: * -> *) k
= Array [value] (value -> k) = Array [value] (value -> k)
@ -438,19 +441,20 @@ instance Effect (Array value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
newtype ArrayC value m a = ArrayC { runArrayC :: m a } newtype ArrayC value m a = ArrayC { runArrayC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
runArray :: Carrier (Array value :+: sig) (ArrayC value (Eff m)) runArray :: Evaluator term address value (ArrayC value m) a
=> Evaluator term address value (ArrayC value (Eff m)) a -> Evaluator term address value m a
-> Evaluator term address value m a runArray = raiseHandler runArrayC
runArray = raiseHandler $ runArrayC . interpret
-- | Construct a hash out of pairs. -- | Construct a hash out of pairs.
hash :: (Member (Hash value) sig, Carrier sig m) => [(value, value)] -> m value hash :: (Member (Hash value) sig, Carrier sig m) => [(value, value)] -> m value
hash v = send (Hash v ret) hash v = send (Hash v pure)
-- | Construct a key-value pair for use in a hash. -- | Construct a key-value pair for use in a hash.
kvPair :: (Member (Hash value) sig, Carrier sig m) => value -> value -> m value kvPair :: (Member (Hash value) sig, Carrier sig m) => value -> value -> m value
kvPair v1 v2 = send (KvPair v1 v2 ret) kvPair v1 v2 = send (KvPair v1 v2 pure)
data Hash value (m :: * -> *) k data Hash value (m :: * -> *) k
= Hash [(value, value)] (value -> k) = Hash [(value, value)] (value -> k)
@ -465,11 +469,12 @@ instance Effect (Hash value) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
newtype HashC value m a = HashC { runHashC :: m a } newtype HashC value m a = HashC { runHashC :: m a }
deriving stock Functor
deriving newtype (Alternative, Applicative, Monad)
runHash :: Carrier (Hash value :+: sig) (HashC value (Eff m)) runHash :: Evaluator term address value (HashC value m) a
=> Evaluator term address value (HashC value (Eff m)) a -> Evaluator term address value m a
-> Evaluator term address value m a runHash = raiseHandler runHashC
runHash = raiseHandler $ runHashC . interpret
class Show value => AbstractIntro value where class Show value => AbstractIntro value where
-- | Construct the nil/null datatype. -- | Construct the nil/null datatype.

View File

@ -1,4 +1,4 @@
{-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, LambdaCase, {-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving,
MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-} MultiParamTypeClasses, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
-- | An effect that enables catching exceptions thrown from -- | An effect that enables catching exceptions thrown from
@ -11,7 +11,7 @@ module Control.Effect.Catch
) where ) where
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Internal import Control.Effect.Reader
import Control.Effect.Sum import Control.Effect.Sum
import qualified Control.Exception as Exc import qualified Control.Exception as Exc
import Control.Monad.IO.Class import Control.Monad.IO.Class
@ -37,26 +37,25 @@ catch :: (Member Catch sig, Carrier sig m, Exc.Exception e)
=> m a => m a
-> (e -> m a) -> (e -> m a)
-> m a -> m a
catch go cleanup = send (CatchIO go cleanup ret) catch go cleanup = send (CatchIO go cleanup pure)
runCatch :: (Carrier sig m, MonadIO m)
=> (forall x . m x -> IO x)
-> Eff (CatchC m) a
-> m a
runCatch handler = runCatchC handler . interpret
newtype CatchC m a = CatchC ((forall x . m x -> IO x) -> m a) -- | Evaulate a 'Catch' effect.
runCatch :: (forall x . m x -> IO x)
-> CatchC m a
-> m a
runCatch handler = runReader (Handler handler) . runCatchC
runCatchC :: (forall x . m x -> IO x) -> CatchC m a -> m a newtype Handler m = Handler (forall x . m x -> IO x)
runCatchC handler (CatchC m) = m handler
runHandler :: Handler m -> CatchC m a -> IO a
runHandler h@(Handler handler) = handler . runReader h . runCatchC
newtype CatchC m a = CatchC { runCatchC :: ReaderC (Handler m) m a }
deriving (Functor, Applicative, Monad, MonadIO)
instance (Carrier sig m, MonadIO m) => Carrier (Catch :+: sig) (CatchC m) where instance (Carrier sig m, MonadIO m) => Carrier (Catch :+: sig) (CatchC m) where
ret a = CatchC (const (ret a)) eff (L (CatchIO act cleanup k)) = do
eff op = CatchC (\ handler -> handleSum handler <- CatchC ask
(eff . handlePure (runCatchC handler)) liftIO (Exc.catch (runHandler handler act) (runHandler handler . cleanup)) >>= k
(\case eff (R other) = CatchC (eff (R (handleCoercible other)))
CatchIO go cleanup k -> liftIO (Exc.catch
(handler (runCatchC handler go))
(handler . runCatchC handler . cleanup))
>>= runCatchC handler . k
) op)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ExistentialQuantification, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification, GeneralizedNewtypeDeriving, RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
module Control.Effect.Interpose module Control.Effect.Interpose
( Interpose(..) ( Interpose(..)
, interpose , interpose
@ -7,8 +7,9 @@ module Control.Effect.Interpose
, Listener(..) , Listener(..)
) where ) where
import Control.Applicative
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Internal import Control.Effect.Reader
import Control.Effect.Sum import Control.Effect.Sum
data Interpose eff m k data Interpose eff m k
@ -28,22 +29,28 @@ interpose :: (Member (Interpose eff) sig, Carrier sig m)
=> m a => m a
-> (forall n x . eff n (n x) -> m x) -> (forall n x . eff n (n x) -> m x)
-> m a -> m a
interpose m f = send (Interpose m f ret) interpose m f = send (Interpose m f pure)
-- | Run an 'Interpose' effect. -- | Run an 'Interpose' effect.
runInterpose :: (Member eff sig, Carrier sig m, Monad m) => Eff (InterposeC eff m) a -> m a runInterpose :: InterposeC eff m a -> m a
runInterpose = flip runInterposeC Nothing . interpret runInterpose = runReader Nothing . runInterposeC
newtype InterposeC eff m a = InterposeC { runInterposeC :: Maybe (Listener eff m) -> m a } newtype InterposeC eff m a = InterposeC { runInterposeC :: ReaderC (Maybe (Listener eff (InterposeC eff m))) m a }
deriving (Alternative, Applicative, Functor, Monad)
newtype Listener eff m = Listener { runListener :: forall n x . eff n (n x) -> m x } newtype Listener eff m = Listener (forall n x . eff n (n x) -> m x)
instance (Carrier sig m, Member eff sig, Monad m) => Carrier (Interpose eff :+: sig) (InterposeC eff m) where -- TODO: Document the implementation of this, as it is extremely subtle.
ret a = InterposeC (const (ret a))
eff op = InterposeC (\ listener -> handleSum (algOther listener) (alg listener) op) runListener :: Listener eff (InterposeC eff m) -> eff (InterposeC eff m) (InterposeC eff m a) -> InterposeC eff m a
where alg listener (Interpose m h k) = runInterposeC m (Just (Listener (flip runInterposeC listener . h))) >>= flip runInterposeC listener . k runListener (Listener listen) = listen
algOther listener op
| Just listener <- listener instance (Carrier sig m, Member eff sig) => Carrier (Interpose eff :+: sig) (InterposeC eff m) where
, Just eff <- prj op = runListener listener eff eff (L (Interpose m h k)) =
| otherwise = eff (handleReader listener runInterposeC op) InterposeC (local (const (Just (Listener h))) (runInterposeC m)) >>= k
eff (R other) = do
listener <- InterposeC ask
case (listener, prj other) of
(Just listener, Just eff) -> runListener listener eff
_ -> InterposeC (eff (R (handleCoercible other)))

View File

@ -1,4 +1,4 @@
{-# LANGUAGE KindSignatures, LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving, KindSignatures, TypeOperators, UndecidableInstances #-}
module Control.Effect.REPL module Control.Effect.REPL
( REPL (..) ( REPL (..)
@ -13,6 +13,7 @@ import Prologue
import Control.Effect import Control.Effect
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Sum import Control.Effect.Sum
import Control.Effect.Reader
import System.Console.Haskeline import System.Console.Haskeline
import qualified Data.Text as T import qualified Data.Text as T
@ -29,21 +30,25 @@ instance Effect REPL where
handle state handler (Output s k) = Output s (handler (k <$ state)) handle state handler (Output s k) = Output s (handler (k <$ state))
prompt :: (Member REPL sig, Carrier sig m) => Text -> m (Maybe Text) prompt :: (Member REPL sig, Carrier sig m) => Text -> m (Maybe Text)
prompt p = send (Prompt p ret) prompt p = send (Prompt p pure)
output :: (Member REPL sig, Carrier sig m) => Text -> m () output :: (Member REPL sig, Carrier sig m) => Text -> m ()
output s = send (Output s (ret ())) output s = send (Output s (pure ()))
runREPL :: (MonadIO m, Carrier sig m) => Prefs -> Settings IO -> Eff (REPLC m) a -> m a runREPL :: Prefs -> Settings IO -> REPLC m a -> m a
runREPL prefs settings = flip runREPLC (prefs, settings) . interpret runREPL prefs settings = runReader (prefs, settings) . runREPLC
newtype REPLC m a = REPLC { runREPLC :: (Prefs, Settings IO) -> m a } newtype REPLC m a = REPLC { runREPLC :: ReaderC (Prefs, Settings IO) m a }
deriving (Functor, Applicative, Monad, MonadIO)
instance (Carrier sig m, MonadIO m) => Carrier (REPL :+: sig) (REPLC m) where instance (Carrier sig m, MonadIO m) => Carrier (REPL :+: sig) (REPLC m) where
ret = REPLC . const . ret eff (L op) = do
eff op = REPLC (\ args -> handleSum (eff . handleReader args runREPLC) (\case args <- REPLC ask
Prompt p k -> liftIO (uncurry runInputTWithPrefs args (fmap (fmap T.pack) (getInputLine (cyan <> T.unpack p <> plain)))) >>= flip runREPLC args . k case op of
Output s k -> liftIO (uncurry runInputTWithPrefs args (outputStrLn (T.unpack s))) *> runREPLC k args) op) Prompt p k -> liftIO (uncurry runInputTWithPrefs args (fmap (fmap T.pack) (getInputLine (cyan <> T.unpack p <> plain)))) >>= k
Output s k -> liftIO (uncurry runInputTWithPrefs args (outputStrLn (T.unpack s))) *> k
eff (R other) = REPLC (eff (R (handleCoercible other)))
cyan :: String cyan :: String
cyan = "\ESC[1;36m\STX" cyan = "\ESC[1;36m\STX"

View File

@ -1,4 +1,4 @@
{-# LANGUAGE LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE TypeOperators, UndecidableInstances #-}
module Data.Abstract.Address.Hole module Data.Abstract.Address.Hole
( Hole(..) ( Hole(..)
, toMaybe , toMaybe
@ -28,18 +28,16 @@ instance ( Carrier (Allocator address :+: sig) (AllocatorC address m)
, Monad m , Monad m
) )
=> Carrier (Allocator (Hole context address) :+: sig) (AllocatorC (Hole context address) m) where => Carrier (Allocator (Hole context address) :+: sig) (AllocatorC (Hole context address) m) where
ret = promoteA . ret eff (R other) = AllocatorC . eff . handleCoercible $ other
eff = handleSum eff (L (Alloc name k)) = Total <$> promoteA (eff (L (Alloc name pure))) >>= k
(AllocatorC . eff . handleCoercible)
(\ (Alloc name k) -> Total <$> promoteA (eff (L (Alloc name ret))) >>= k)
promoteD :: DerefC address value m a -> DerefC (Hole context address) value m a promoteD :: DerefC address value m a -> DerefC (Hole context address) value m a
promoteD = DerefC . runDerefC promoteD = DerefC . runDerefC
instance (Carrier (Deref value :+: sig) (DerefC address value m), Carrier sig m, Monad m) instance (Carrier (Deref value :+: sig) (DerefC address value m), Carrier sig m)
=> Carrier (Deref value :+: sig) (DerefC (Hole context address) value m) where => Carrier (Deref value :+: sig) (DerefC (Hole context address) value m) where
ret = promoteD . ret eff (R other) = DerefC . eff . handleCoercible $ other
eff = handleSum (DerefC . eff . handleCoercible) (\case eff (L op) = case op of
DerefCell cell k -> promoteD (eff (L (DerefCell cell ret))) >>= k DerefCell cell k -> promoteD (eff (L (DerefCell cell pure))) >>= k
AssignCell value cell k -> promoteD (eff (L (AssignCell value cell ret))) >>= k) AssignCell value cell k -> promoteD (eff (L (AssignCell value cell pure))) >>= k

View File

@ -1,4 +1,4 @@
{-# LANGUAGE LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE TypeOperators, UndecidableInstances #-}
module Data.Abstract.Address.Monovariant module Data.Abstract.Address.Monovariant
( Monovariant(..) ( Monovariant(..)
) where ) where
@ -19,14 +19,10 @@ instance Show Monovariant where
instance Carrier sig m => Carrier (Allocator Monovariant :+: sig) (AllocatorC Monovariant m) where instance Carrier sig m => Carrier (Allocator Monovariant :+: sig) (AllocatorC Monovariant m) where
ret = AllocatorC . ret eff (L (Alloc name k)) = k (Monovariant name)
eff = AllocatorC . handleSum eff (R other) = AllocatorC . eff . handleCoercible $ other
(eff . handleCoercible)
(\ (Alloc name k) -> runAllocatorC (k (Monovariant name)))
instance (Ord value, Carrier sig m, Alternative m, Monad m) => Carrier (Deref value :+: sig) (DerefC Monovariant value m) where instance (Ord value, Carrier sig m, Alternative m, Monad m) => Carrier (Deref value :+: sig) (DerefC Monovariant value m) where
ret = DerefC . ret eff (L (DerefCell cell k)) = traverse (foldMapA pure) (nonEmpty (toList cell)) >>= k
eff = DerefC . handleSum (eff . handleCoercible) (\case eff (L (AssignCell value cell k)) = k (Set.insert value cell)
DerefCell cell k -> traverse (foldMapA pure) (nonEmpty (toList cell)) >>= runDerefC . k eff (R other) = DerefC . eff . handleCoercible $ other
AssignCell value cell k -> runDerefC (k (Set.insert value cell)))

View File

@ -1,4 +1,4 @@
{-# LANGUAGE GeneralizedNewtypeDeriving, LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances #-}
module Data.Abstract.Address.Precise module Data.Abstract.Address.Precise
( Precise(..) ( Precise(..)
) where ) where
@ -18,15 +18,13 @@ instance Show Precise where
showsPrec d = showsUnaryWith showsPrec "Precise" d . unPrecise showsPrec d = showsUnaryWith showsPrec "Precise" d . unPrecise
instance (Member Fresh sig, Carrier sig m, Monad m) => Carrier (Allocator Precise :+: sig) (AllocatorC Precise m) where instance (Member Fresh sig, Carrier sig m) => Carrier (Allocator Precise :+: sig) (AllocatorC Precise m) where
ret = AllocatorC . ret eff (R other) = AllocatorC . eff . handleCoercible $ other
eff = AllocatorC . handleSum eff (L (Alloc _ k)) = Precise <$> fresh >>= k
(eff . handleCoercible)
(\ (Alloc _ k) -> Precise <$> fresh >>= runAllocatorC . k)
instance Carrier sig m => Carrier (Deref value :+: sig) (DerefC Precise value m) where instance Carrier sig m => Carrier (Deref value :+: sig) (DerefC Precise value m) where
ret = DerefC . ret eff (R other) = DerefC . eff . handleCoercible $ other
eff = DerefC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
DerefCell cell k -> runDerefC (k (fst <$> Set.minView cell)) DerefCell cell k -> k (fst <$> Set.minView cell)
AssignCell value _ k -> runDerefC (k (Set.singleton value))) AssignCell value _ k -> k (Set.singleton value)

View File

@ -39,7 +39,6 @@ throwBaseError :: ( Member (Resumable (BaseError exc)) sig
, Member (Reader M.ModuleInfo) sig , Member (Reader M.ModuleInfo) sig
, Member (Reader S.Span) sig , Member (Reader S.Span) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> exc resume => exc resume
-> m resume -> m resume

View File

@ -258,10 +258,13 @@ instance (Eq term, Eq value) => Eq1 (EvalError term address value) where
instance (Show term, Show value) => Show1 (EvalError term address value) where instance (Show term, Show value) => Show1 (EvalError term address value) where
liftShowsPrec _ _ = showsPrec liftShowsPrec _ _ = showsPrec
runEvalError :: (Carrier sig m, Effect sig) => Evaluator term address value (ResumableC (BaseError (EvalError term address value)) (Eff m)) a -> Evaluator term address value m (Either (SomeError (BaseError (EvalError term address value))) a) runEvalError :: Evaluator term address value (ResumableC (BaseError (EvalError term address value)) m) a
-> Evaluator term address value m (Either (SomeError (BaseError (EvalError term address value))) a)
runEvalError = raiseHandler runResumable runEvalError = raiseHandler runResumable
runEvalErrorWith :: Carrier sig m => (forall resume . (BaseError (EvalError term address value)) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError (EvalError term address value)) (Eff m)) a -> Evaluator term address value m a runEvalErrorWith :: (forall resume . (BaseError (EvalError term address value)) resume -> Evaluator term address value m resume)
-> Evaluator term address value (ResumableWithC (BaseError (EvalError term address value)) m) a
-> Evaluator term address value m a
runEvalErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runEvalErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)
throwEvalError :: ( Member (Reader ModuleInfo) sig throwEvalError :: ( Member (Reader ModuleInfo) sig
@ -297,14 +300,12 @@ instance Eq1 (UnspecializedError address value) where
instance Show1 (UnspecializedError address value) where instance Show1 (UnspecializedError address value) where
liftShowsPrec _ _ = showsPrec liftShowsPrec _ _ = showsPrec
runUnspecialized :: (Carrier sig m, Effect sig) runUnspecialized :: Evaluator term address value (ResumableC (BaseError (UnspecializedError address value)) m) a
=> Evaluator term address value (ResumableC (BaseError (UnspecializedError address value)) (Eff m)) a
-> Evaluator term address value m (Either (SomeError (BaseError (UnspecializedError address value))) a) -> Evaluator term address value m (Either (SomeError (BaseError (UnspecializedError address value))) a)
runUnspecialized = raiseHandler runResumable runUnspecialized = raiseHandler runResumable
runUnspecializedWith :: Carrier sig m runUnspecializedWith :: (forall resume . BaseError (UnspecializedError address value) resume -> Evaluator term address value m resume)
=> (forall resume . BaseError (UnspecializedError address value) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError (UnspecializedError address value)) m) a
-> Evaluator term address value (ResumableWithC (BaseError (UnspecializedError address value)) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runUnspecializedWith f = raiseHandler $ runResumableWith (runEvaluator . f) runUnspecializedWith f = raiseHandler $ runResumableWith (runEvaluator . f)

View File

@ -24,7 +24,7 @@ data Name
deriving (Eq, Ord, Generic, NFData) deriving (Eq, Ord, Generic, NFData)
-- | Generate a fresh (unused) name for use in synthesized variables/closures/etc. -- | Generate a fresh (unused) name for use in synthesized variables/closures/etc.
gensym :: (Member Fresh sig, Carrier sig m, Functor m) => m Name gensym :: (Member Fresh sig, Carrier sig m) => m Name
gensym = I <$> fresh gensym = I <$> fresh
-- | Construct a 'Name' from a 'Text'. -- | Construct a 'Name' from a 'Text'.

View File

@ -1,4 +1,4 @@
{-# LANGUAGE LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE TypeOperators, UndecidableInstances #-}
module Data.Abstract.Value.Abstract module Data.Abstract.Value.Abstract
( Abstract (..) ( Abstract (..)
, runFunction , runFunction
@ -38,100 +38,95 @@ instance ( Member (Allocator address) sig
, Show address , Show address
, Carrier sig m , Carrier sig m
) )
=> Carrier (Abstract.Function term address Abstract :+: sig) (FunctionC term address Abstract (Eff m)) where => Carrier (Abstract.Function term address Abstract :+: sig) (FunctionC term address Abstract m) where
ret = FunctionC . const . ret eff (R other) = FunctionC . eff . R . handleCoercible $ other
eff op = FunctionC (\ eval -> handleSum (eff . handleReader eval runFunctionC) (\case eff (L op) = runEvaluator $ do
Function _ params body scope k -> runEvaluator $ do eval <- Evaluator . FunctionC $ ask
currentScope' <- currentScope case op of
currentFrame' <- currentFrame Function _ params body scope k -> do
let frameLinks = Map.singleton Lexical (Map.singleton currentScope' currentFrame') currentScope' <- currentScope
frame <- newFrame scope frameLinks currentFrame' <- currentFrame
res <- withScopeAndFrame frame $ do let frameLinks = Map.singleton Lexical (Map.singleton currentScope' currentFrame')
for_ params $ \param -> do frame <- newFrame scope frameLinks
slot <- lookupSlot (Declaration param) res <- withScopeAndFrame frame $ do
assign slot Abstract for_ params $ \param -> do
catchReturn (runFunction (Evaluator . eval) (Evaluator (eval body))) slot <- lookupSlot (Declaration param)
Evaluator $ runFunctionC (k res) eval assign slot Abstract
BuiltIn _ _ k -> runFunctionC (k Abstract) eval catchReturn (Evaluator (eval body))
Bind _ _ k -> runFunctionC (k Abstract) eval Evaluator (k res)
Call _ _ k -> runFunctionC (k Abstract) eval) op) BuiltIn _ _ k -> Evaluator (k Abstract)
Bind _ _ k -> Evaluator (k Abstract)
Call _ _ k -> Evaluator (k Abstract)
instance (Carrier sig m, Alternative m) => Carrier (Boolean Abstract :+: sig) (BooleanC Abstract m) where instance (Carrier sig m, Alternative m) => Carrier (Boolean Abstract :+: sig) (BooleanC Abstract m) where
ret = BooleanC . ret eff (L (Boolean _ k)) = k Abstract
eff = BooleanC . handleSum (eff . handleCoercible) (\case eff (L (AsBool _ k)) = k True <|> k False
Boolean _ k -> runBooleanC (k Abstract) eff (R other) = BooleanC . eff . handleCoercible $ other
AsBool _ k -> runBooleanC (k True) <|> runBooleanC (k False))
instance ( Member (Abstract.Boolean Abstract) sig instance ( Member (Abstract.Boolean Abstract) sig
, Carrier sig m , Carrier sig m
, Alternative m , Alternative m
, Monad m
) )
=> Carrier (While Abstract :+: sig) (WhileC Abstract m) where => Carrier (While Abstract :+: sig) (WhileC Abstract m) where
ret = WhileC . ret eff (R other) = WhileC . eff . handleCoercible $ other
eff = WhileC . handleSum eff (L (Abstract.While cond body k)) = do
(eff . handleCoercible) cond' <- cond
(\ (Abstract.While cond body k) -> do ifthenelse cond' (body *> empty) (k Abstract)
cond' <- runWhileC cond
ifthenelse cond' (runWhileC body *> empty) (runWhileC (k Abstract)))
instance Carrier sig m instance Carrier sig m
=> Carrier (Unit Abstract :+: sig) (UnitC Abstract m) where => Carrier (Unit Abstract :+: sig) (UnitC Abstract m) where
ret = UnitC . ret eff (R other) = UnitC . eff . handleCoercible $ other
eff = UnitC . handleSum eff (L (Abstract.Unit k)) = k Abstract
(eff . handleCoercible)
(\ (Abstract.Unit k) -> runUnitC (k Abstract))
instance Carrier sig m instance Carrier sig m
=> Carrier (Abstract.String Abstract :+: sig) (StringC Abstract m) where => Carrier (Abstract.String Abstract :+: sig) (StringC Abstract m) where
ret = StringC . ret eff (R other) = StringC . eff . handleCoercible $ other
eff = StringC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.String _ k -> runStringC (k Abstract) Abstract.String _ k -> k Abstract
AsString _ k -> runStringC (k "")) AsString _ k -> k ""
instance Carrier sig m instance Carrier sig m
=> Carrier (Numeric Abstract :+: sig) (NumericC Abstract m) where => Carrier (Numeric Abstract :+: sig) (NumericC Abstract m) where
ret = NumericC . ret eff (R other) = NumericC . eff . handleCoercible $ other
eff = NumericC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Integer _ k -> runNumericC (k Abstract) Integer _ k -> k Abstract
Float _ k -> runNumericC (k Abstract) Float _ k -> k Abstract
Rational _ k -> runNumericC (k Abstract) Rational _ k -> k Abstract
LiftNumeric _ _ k -> runNumericC (k Abstract) LiftNumeric _ _ k -> k Abstract
LiftNumeric2 _ _ _ k -> runNumericC (k Abstract)) LiftNumeric2 _ _ _ k -> k Abstract
instance Carrier sig m instance Carrier sig m
=> Carrier (Bitwise Abstract :+: sig) (BitwiseC Abstract m) where => Carrier (Bitwise Abstract :+: sig) (BitwiseC Abstract m) where
ret = BitwiseC . ret eff (R other) = BitwiseC . eff . handleCoercible $ other
eff = BitwiseC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
CastToInteger _ k -> runBitwiseC (k Abstract) CastToInteger _ k -> k Abstract
LiftBitwise _ _ k -> runBitwiseC (k Abstract) LiftBitwise _ _ k -> k Abstract
LiftBitwise2 _ _ _ k -> runBitwiseC (k Abstract) LiftBitwise2 _ _ _ k -> k Abstract
UnsignedRShift _ _ k -> runBitwiseC (k Abstract)) UnsignedRShift _ _ k -> k Abstract
instance Carrier sig m instance Carrier sig m
=> Carrier (Object address Abstract :+: sig) (ObjectC address Abstract m) where => Carrier (Object address Abstract :+: sig) (ObjectC address Abstract m) where
ret = ObjectC . ret eff (R other) = ObjectC . eff . handleCoercible $ other
eff = ObjectC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Object _ k -> runObjectC (k Abstract) Object _ k -> k Abstract
ScopedEnvironment _ k -> runObjectC (k Nothing) ScopedEnvironment _ k -> k Nothing
Klass _ _ k -> runObjectC (k Abstract)) Klass _ _ k -> k Abstract
instance Carrier sig m instance Carrier sig m
=> Carrier (Array Abstract :+: sig) (ArrayC Abstract m) where => Carrier (Array Abstract :+: sig) (ArrayC Abstract m) where
ret = ArrayC . ret eff (R other) = ArrayC . eff . handleCoercible $ other
eff = ArrayC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Array _ k -> runArrayC (k Abstract) Array _ k -> k Abstract
AsArray _ k -> runArrayC (k [])) AsArray _ k -> k []
instance Carrier sig m instance Carrier sig m
=> Carrier (Hash Abstract :+: sig) (HashC Abstract m) where => Carrier (Hash Abstract :+: sig) (HashC Abstract m) where
ret = HashC . ret eff (R other) = HashC . eff . handleCoercible $ other
eff = HashC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Hash _ k -> runHashC (k Abstract) Hash _ k -> k Abstract
KvPair _ _ k -> runHashC (k Abstract)) KvPair _ _ k -> k Abstract
instance Ord address => ValueRoots address Abstract where instance Ord address => ValueRoots address Abstract where
@ -143,7 +138,7 @@ instance AbstractHole Abstract where
instance AbstractIntro Abstract where instance AbstractIntro Abstract where
null = Abstract null = Abstract
instance AbstractValue term address Abstract m where instance Applicative m => AbstractValue term address Abstract m where
tuple _ = pure Abstract tuple _ = pure Abstract
namespace _ _ = pure Abstract namespace _ _ = pure Abstract

View File

@ -1,4 +1,4 @@
{-# LANGUAGE DeriveAnyClass, GADTs, RankNTypes, TypeOperators, UndecidableInstances, LambdaCase, ScopedTypeVariables #-} {-# LANGUAGE DeriveAnyClass, GADTs, LambdaCase, RankNTypes, TypeOperators, UndecidableInstances, ScopedTypeVariables #-}
module Data.Abstract.Value.Concrete module Data.Abstract.Value.Concrete
( Value (..) ( Value (..)
, ValueError (..) , ValueError (..)
@ -26,6 +26,7 @@ import Data.Text (pack)
import Data.Word import Data.Word
import Prologue import Prologue
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Debug.Trace (traceM)
data Value term address data Value term address
-- TODO: Split Closure up into a separate data type. Scope Frame -- TODO: Split Closure up into a separate data type. Scope Frame
@ -77,47 +78,48 @@ instance ( FreeVariables term
, Show address , Show address
, Show term , Show term
) )
=> Carrier (Abstract.Function term address (Value term address) :+: sig) (Abstract.FunctionC term address (Value term address) (Eff m)) where => Carrier (Abstract.Function term address (Value term address) :+: sig) (Abstract.FunctionC term address (Value term address) m) where
ret = FunctionC . const . ret eff (R other) = FunctionC . eff . R . handleCoercible $ other
eff op = eff (L op) = runEvaluator $ do
eval <- Evaluator . FunctionC $ ask
let closure maybeName params body scope = do let closure maybeName params body scope = do
packageInfo <- currentPackage packageInfo <- currentPackage
moduleInfo <- currentModule moduleInfo <- currentModule
Closure packageInfo moduleInfo maybeName Nothing params body scope <$> currentFrame Closure packageInfo moduleInfo maybeName Nothing params body scope <$> currentFrame
in FunctionC (\ eval -> handleSum (eff . handleReader eval runFunctionC) (\case case op of
Abstract.Function name params body scope k -> runEvaluator $ do Abstract.Function name params body scope k -> do
val <- closure (Just name) params (Right body) scope val <- closure (Just name) params (Right body) scope
Evaluator $ runFunctionC (k val) eval Evaluator (k val)
Abstract.BuiltIn associatedScope builtIn k -> runEvaluator $ do Abstract.BuiltIn associatedScope builtIn k -> do
val <- closure Nothing [] (Left builtIn) associatedScope val <- closure Nothing [] (Left builtIn) associatedScope
Evaluator $ runFunctionC (k val) eval Evaluator (k val)
Abstract.Bind obj@Object{} (Closure packageInfo moduleInfo name _ names body scope parentFrame) k -> Abstract.Bind obj@Object{} (Closure packageInfo moduleInfo name _ names body scope parentFrame) k ->
runFunctionC (k (Closure packageInfo moduleInfo name (Just obj) names body scope parentFrame)) eval Evaluator (k (Closure packageInfo moduleInfo name (Just obj) names body scope parentFrame))
Abstract.Bind _ value k -> runFunctionC (k value) eval Abstract.Bind _ value k -> Evaluator (k value)
Abstract.Call op params k -> runEvaluator $ do Abstract.Call op params k -> do
boxed <- case op of boxed <- case op of
Closure _ _ _ _ _ (Left Print) _ _ -> traverse (trace . show) params $> Unit Closure _ _ _ _ _ (Left Print) _ _ -> traverse (trace . show) params $> Unit
Closure _ _ _ _ _ (Left Show) _ _ -> pure . String . pack $ show params Closure _ _ _ _ _ (Left Show) _ _ -> pure . String . pack $ show params
Closure packageInfo moduleInfo _ maybeSelf names (Right body) associatedScope parentFrame -> do Closure packageInfo moduleInfo _ maybeSelf names (Right body) associatedScope parentFrame -> do
-- Evaluate the bindings and body with the closures package/module info in scope in order to -- Evaluate the bindings and body with the closures package/module info in scope in order to
-- charge them to the closure's origin. -- charge them to the closure's origin.
withCurrentPackage packageInfo . withCurrentModule moduleInfo $ do withCurrentPackage packageInfo . withCurrentModule moduleInfo $ do
parentScope <- scopeLookup parentFrame parentScope <- scopeLookup parentFrame
let frameEdges = Map.singleton Lexical (Map.singleton parentScope parentFrame) let frameEdges = Map.singleton Lexical (Map.singleton parentScope parentFrame)
frameAddress <- newFrame associatedScope frameEdges frameAddress <- newFrame associatedScope frameEdges
withScopeAndFrame frameAddress $ do withScopeAndFrame frameAddress $ do
case maybeSelf of case maybeSelf of
Just object -> do Just object -> do
maybeSlot <- maybeLookupDeclaration (Declaration __self) maybeSlot <- maybeLookupDeclaration (Declaration __self)
maybe (pure ()) (`assign` object) maybeSlot maybe (pure ()) (`assign` object) maybeSlot
Nothing -> pure () Nothing -> pure ()
for_ (zip names params) $ \(name, param) -> do for_ (zip names params) $ \(name, param) -> do
slot <- lookupSlot (Declaration name) slot <- lookupSlot (Declaration name)
assign slot param assign slot param
catchReturn (runFunction (Evaluator . eval) (Evaluator (eval body))) catchReturn (Evaluator (eval body))
_ -> throwValueError (CallError op) _ -> throwValueError (CallError op)
Evaluator $ runFunctionC (k boxed) eval) op) Evaluator (k boxed)
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -126,49 +128,78 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Boolean (Value term address) :+: sig) (BooleanC (Value term address) m) where => Carrier (Abstract.Boolean (Value term address) :+: sig) (BooleanC (Value term address) m) where
ret = BooleanC . ret eff (R other) = BooleanC . eff . handleCoercible $ other
eff = BooleanC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Boolean b k -> runBooleanC . k $! Boolean b Abstract.Boolean b k -> k $! Boolean b
Abstract.AsBool (Boolean b) k -> runBooleanC (k b) Abstract.AsBool (Boolean b) k -> k b
Abstract.AsBool other k -> throwBaseError (BoolError other) >>= runBooleanC . k) Abstract.AsBool other k -> throwBaseError (BoolError other) >>= k
instance ( Carrier sig m instance ( Carrier sig m
, Member (Abstract.Boolean (Value term address)) sig , Member (Abstract.Boolean (Value term address)) sig
, Member (Error (LoopControl (Value term address))) sig , Member (Error (LoopControl (Value term address))) sig
, Member (Interpose (Resumable (BaseError (UnspecializedError address (Value term address))))) sig , Member (Interpose (Resumable (BaseError (UnspecializedError address (Value term address))))) sig
) )
=> Carrier (Abstract.While (Value term address) :+: sig) (WhileC (Value term address) (Eff m)) where => Carrier (Abstract.While (Value term address) :+: sig) (WhileC (Value term address) m) where
ret = WhileC . ret eff (R other) = WhileC . eff . handleCoercible $ other
eff = WhileC . handleSum (eff . handleCoercible) (\case eff (L (Abstract.While cond body k)) = do
Abstract.While cond body k -> interpose @(Resumable (BaseError (UnspecializedError address (Value term address)))) (runEvaluator (loop (\continue -> do
cond' <- Evaluator (runWhileC cond) let loop x = catchError x $ \case
Break value -> pure value
Abort -> pure Unit
-- FIXME: Figure out how to deal with this. Ruby treats this as the result
-- of the current block iteration, while PHP specifies a breakout level
-- and TypeScript appears to take a label.
Continue _ -> loop x
interpose @(Resumable (BaseError (UnspecializedError address (Value term address)))) (loop (do
cond' <- cond
-- `interpose` is used to handle 'UnspecializedError's and abort out of the -- `interpose` is used to handle 'UnspecializedError's and abort out of the
-- loop, otherwise under concrete semantics we run the risk of the -- loop, otherwise under concrete semantics we run the risk of the
-- conditional always being true and getting stuck in an infinite loop. -- conditional always being true and getting stuck in an infinite loop.
ifthenelse cond' (body *> throwError (Continue @(Value term address) Unit)) (pure Unit)))
ifthenelse cond' (Evaluator (runWhileC body) *> continue) (pure Unit))))
(\case (\case
Resumable (BaseError _ _ (UnspecializedError _)) _ -> throwError (Abort @(Value term address)) Resumable (BaseError _ _ (UnspecializedError _)) _ -> traceM "unspecialized" *> throwError (Abort @(Value term address))
Resumable (BaseError _ _ (RefUnspecializedError _)) _ -> throwError (Abort @(Value term address))) Resumable (BaseError _ _ (RefUnspecializedError _)) _ -> traceM "refun" *> throwError (Abort @(Value term address))) >>= k
>>= runWhileC . k)
where
loop x = catchLoopControl (fix x) $ \case
Break value -> pure value -- Abstract.While cond body k -> interpose @(Resumable (BaseError (UnspecializedError address (Value term address)))) (runEvaluator (loop (\continue -> do cond' <- Evaluator (runWhileC cond)
Abort -> pure Unit
-- FIXME: Figure out how to deal with this. Ruby treats this as the result -- -- `interpose` is used to handle 'UnspecializedError's and abort out of the
-- of the current block iteration, while PHP specifies a breakout level -- -- loop, otherwise under concrete semantics we run the risk of the
-- and TypeScript appears to take a label. -- -- conditional always being true and getting stuck in an infinite loop.
Continue _ -> loop x
-- ifthenelse cond' (Evaluator (runWhileC body) *> continue) (pure Unit))))
-- (
-- >>= runWhileC . k)
-- where
-- loop x = catchLoopControl (fix x) $ \case
-- Break value -> pure value
-- Abort -> pure Unit
-- -- FIXME: Figure out how to deal with this. Ruby treats this as the result
-- -- of the current block iteration, while PHP specifies a breakout level
-- -- and TypeScript appears to take a label.
-- Continue _ -> loop x
-- case op of
-- Abstract.While cond body k -> interpose @(Resumable (BaseError (UnspecializedError address (Value term address)))) (runEvaluator (loop (\continue -> do
-- cond' <- Evaluator (runWhileC cond)
-- -- `interpose` is used to handle 'UnspecializedError's and abort out of the
-- -- loop, otherwise under concrete semantics we run the risk of the
-- -- conditional always being true and getting stuck in an infinite loop.
-- ifthenelse cond' (Evaluator (runWhileC body) *> continue) (pure Unit)
-- case _ of
-- Resumable (BaseError _ _ (UnspecializedError _)) _ -> throwError (Abort @(Value term address)) >>= k
-- Resumable (BaseError _ _ (RefUnspecializedError _)) _ -> throwError (Abort @(Value term address))) >>= k
instance Carrier sig m instance Carrier sig m
=> Carrier (Abstract.Unit (Value term address) :+: sig) (UnitC (Value term address) m) where => Carrier (Abstract.Unit (Value term address) :+: sig) (UnitC (Value term address) m) where
ret = UnitC . ret eff (R other) = UnitC . eff . handleCoercible $ other
eff = UnitC . handleSum eff (L (Abstract.Unit k )) = k Unit
(eff . handleCoercible)
(\ (Abstract.Unit k) -> runUnitC (k Unit))
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -177,11 +208,11 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.String (Value term address) :+: sig) (StringC (Value term address) m) where => Carrier (Abstract.String (Value term address) :+: sig) (StringC (Value term address) m) where
ret = StringC . ret eff (R other) = StringC . eff . handleCoercible $ other
eff = StringC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.String t k -> runStringC (k (String t)) Abstract.String t k -> k (String t)
Abstract.AsString (String t) k -> runStringC (k t) Abstract.AsString (String t) k -> k t
Abstract.AsString other k -> throwBaseError (StringError other) >>= runStringC . k) Abstract.AsString other k -> throwBaseError (StringError other) >>= k
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -190,17 +221,17 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Numeric (Value term address) :+: sig) (NumericC (Value term address) m) where => Carrier (Abstract.Numeric (Value term address) :+: sig) (NumericC (Value term address) m) where
ret = NumericC . ret eff (R other) = NumericC . eff . handleCoercible $ other
eff = NumericC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Integer t k -> runNumericC (k (Integer (Number.Integer t))) Abstract.Integer t k -> k (Integer (Number.Integer t))
Abstract.Float t k -> runNumericC (k (Float (Number.Decimal t))) Abstract.Float t k -> k (Float (Number.Decimal t))
Abstract.Rational t k -> runNumericC (k (Rational (Number.Ratio t))) Abstract.Rational t k -> k (Rational (Number.Ratio t))
Abstract.LiftNumeric f arg k -> runNumericC . k =<< case arg of Abstract.LiftNumeric f arg k -> k =<< case arg of
Integer (Number.Integer i) -> pure $ Integer (Number.Integer (f i)) Integer (Number.Integer i) -> pure $ Integer (Number.Integer (f i))
Float (Number.Decimal d) -> pure $ Float (Number.Decimal (f d)) Float (Number.Decimal d) -> pure $ Float (Number.Decimal (f d))
Rational (Number.Ratio r) -> pure $ Rational (Number.Ratio (f r)) Rational (Number.Ratio r) -> pure $ Rational (Number.Ratio (f r))
other -> throwBaseError (NumericError other) other -> throwBaseError (NumericError other)
Abstract.LiftNumeric2 f left right k -> runNumericC . k =<< case (left, right) of Abstract.LiftNumeric2 f left right k -> k =<< case (left, right) of
(Integer i, Integer j) -> attemptUnsafeArithmetic (f i j) & specialize (Integer i, Integer j) -> attemptUnsafeArithmetic (f i j) & specialize
(Integer i, Rational j) -> attemptUnsafeArithmetic (f i j) & specialize (Integer i, Rational j) -> attemptUnsafeArithmetic (f i j) & specialize
(Integer i, Float j) -> attemptUnsafeArithmetic (f i j) & specialize (Integer i, Float j) -> attemptUnsafeArithmetic (f i j) & specialize
@ -210,21 +241,20 @@ instance ( Member (Reader ModuleInfo) sig
(Float i, Integer j) -> attemptUnsafeArithmetic (f i j) & specialize (Float i, Integer j) -> attemptUnsafeArithmetic (f i j) & specialize
(Float i, Rational j) -> attemptUnsafeArithmetic (f i j) & specialize (Float i, Rational j) -> attemptUnsafeArithmetic (f i j) & specialize
(Float i, Float j) -> attemptUnsafeArithmetic (f i j) & specialize (Float i, Float j) -> attemptUnsafeArithmetic (f i j) & specialize
_ -> throwBaseError (Numeric2Error left right)) _ -> throwBaseError (Numeric2Error left right)
-- Dispatch whatever's contained inside a 'Number.SomeNumber' to its appropriate 'MonadValue' ctor -- Dispatch whatever's contained inside a 'Number.SomeNumber' to its appropriate 'MonadValue' ctor
specialize :: ( Member (Reader ModuleInfo) sig specialize :: ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
, Member (Resumable (BaseError (ValueError term address))) sig , Member (Resumable (BaseError (ValueError term address))) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> Either ArithException Number.SomeNumber => Either ArithException Number.SomeNumber
-> m (Value term address) -> m (Value term address)
specialize (Left exc) = throwBaseError (ArithmeticError exc) specialize (Left exc) = throwBaseError (ArithmeticError exc)
specialize (Right (Number.SomeNumber (Number.Integer t))) = pure (Integer (Number.Integer t)) specialize (Right (Number.SomeNumber (Number.Integer t))) = pure (Integer (Number.Integer t))
specialize (Right (Number.SomeNumber (Number.Decimal t))) = pure (Float (Number.Decimal t)) specialize (Right (Number.SomeNumber (Number.Decimal t))) = pure (Float (Number.Decimal t))
specialize (Right (Number.SomeNumber (Number.Ratio t))) = pure (Rational (Number.Ratio t)) specialize (Right (Number.SomeNumber (Number.Ratio t))) = pure (Rational (Number.Ratio t))
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
@ -234,32 +264,31 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Bitwise (Value term address) :+: sig) (BitwiseC (Value term address) m) where => Carrier (Abstract.Bitwise (Value term address) :+: sig) (BitwiseC (Value term address) m) where
ret = BitwiseC . ret eff (R other) = BitwiseC . eff . handleCoercible $ other
eff = BitwiseC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
CastToInteger (Integer (Number.Integer i)) k -> runBitwiseC (k (Integer (Number.Integer i))) CastToInteger (Integer (Number.Integer i)) k -> k (Integer (Number.Integer i))
CastToInteger (Float (Number.Decimal i)) k -> runBitwiseC (k (Integer (Number.Integer (coefficient (normalize i))))) CastToInteger (Float (Number.Decimal i)) k -> k (Integer (Number.Integer (coefficient (normalize i))))
CastToInteger i k -> throwBaseError (NumericError i) >>= runBitwiseC . k CastToInteger i k -> throwBaseError (NumericError i) >>= k
LiftBitwise operator (Integer (Number.Integer i)) k -> runBitwiseC . k . Integer . Number.Integer . operator $ i LiftBitwise operator (Integer (Number.Integer i)) k -> k . Integer . Number.Integer . operator $ i
LiftBitwise _ other k -> throwBaseError (BitwiseError other) >>= runBitwiseC . k LiftBitwise _ other k -> throwBaseError (BitwiseError other) >>= k
LiftBitwise2 operator (Integer (Number.Integer i)) (Integer (Number.Integer j)) k -> runBitwiseC . k . Integer . Number.Integer $ operator i j LiftBitwise2 operator (Integer (Number.Integer i)) (Integer (Number.Integer j)) k -> k . Integer . Number.Integer $ operator i j
LiftBitwise2 _ left right k -> throwBaseError (Bitwise2Error left right) >>= runBitwiseC . k LiftBitwise2 _ left right k -> throwBaseError (Bitwise2Error left right) >>= k
UnsignedRShift (Integer (Number.Integer i)) (Integer (Number.Integer j)) k | i >= 0 -> runBitwiseC . k . Integer . Number.Integer $ ourShift (fromIntegral i) (fromIntegral j) UnsignedRShift (Integer (Number.Integer i)) (Integer (Number.Integer j)) k | i >= 0 -> k . Integer . Number.Integer $ ourShift (fromIntegral i) (fromIntegral j)
UnsignedRShift left right k -> throwBaseError (Bitwise2Error left right) >>= runBitwiseC . k) UnsignedRShift left right k -> throwBaseError (Bitwise2Error left right) >>= k
ourShift :: Word64 -> Int -> Integer ourShift :: Word64 -> Int -> Integer
ourShift a b = toInteger (shiftR a b) ourShift a b = toInteger (shiftR a b)
instance Carrier sig m => Carrier (Abstract.Object address (Value term address) :+: sig) (ObjectC address (Value term address) m) where instance Carrier sig m => Carrier (Abstract.Object address (Value term address) :+: sig) (ObjectC address (Value term address) m) where
ret = ObjectC . ret eff (R other) = ObjectC . eff . handleCoercible $ other
eff = ObjectC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Object address k -> runObjectC (k (Object address)) Abstract.Object address k -> k (Object address)
Abstract.ScopedEnvironment (Object address) k -> runObjectC (k (Just address)) Abstract.ScopedEnvironment (Object address) k -> k (Just address)
Abstract.ScopedEnvironment (Class _ _ address) k -> runObjectC (k (Just address)) Abstract.ScopedEnvironment (Class _ _ address) k -> k (Just address)
Abstract.ScopedEnvironment (Namespace _ address) k -> runObjectC (k (Just address)) Abstract.ScopedEnvironment (Namespace _ address) k -> k (Just address)
Abstract.ScopedEnvironment _ k -> runObjectC (k Nothing) Abstract.ScopedEnvironment _ k -> k Nothing
Abstract.Klass n frame k -> runObjectC (k (Class n mempty frame)) Abstract.Klass n frame k -> k (Class n mempty frame)
)
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -268,17 +297,17 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Array (Value term address) :+: sig) (ArrayC (Value term address) m) where => Carrier (Abstract.Array (Value term address) :+: sig) (ArrayC (Value term address) m) where
ret = ArrayC . ret eff (R other) = ArrayC . eff . handleCoercible $ other
eff = ArrayC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Array t k -> runArrayC (k (Array t)) Abstract.Array t k -> k (Array t)
Abstract.AsArray (Array addresses) k -> runArrayC (k addresses) Abstract.AsArray (Array addresses) k -> k addresses
Abstract.AsArray val k -> throwBaseError (ArrayError val) >>= runArrayC . k) Abstract.AsArray val k -> throwBaseError (ArrayError val) >>= k
instance ( Carrier sig m ) => Carrier (Abstract.Hash (Value term address) :+: sig) (HashC (Value term address) m) where instance ( Carrier sig m ) => Carrier (Abstract.Hash (Value term address) :+: sig) (HashC (Value term address) m) where
ret = HashC . ret eff (R other) = HashC . eff . handleCoercible $ other
eff = HashC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Hash t k -> runHashC (k ((Hash . map (uncurry KVPair)) t)) Abstract.Hash t k -> k ((Hash . map (uncurry KVPair)) t)
Abstract.KvPair t v k -> runHashC (k (KVPair t v))) Abstract.KvPair t v k -> k (KVPair t v)
instance AbstractHole (Value term address) where instance AbstractHole (Value term address) where
@ -391,14 +420,12 @@ deriving instance (Show address, Show term) => Show (ValueError term address res
instance (Show address, Show term) => Show1 (ValueError term address) where instance (Show address, Show term) => Show1 (ValueError term address) where
liftShowsPrec _ _ = showsPrec liftShowsPrec _ _ = showsPrec
runValueError :: (Carrier sig m, Effect sig) runValueError :: Evaluator term address (Value term address) (ResumableC (BaseError (ValueError term address)) m) a
=> Evaluator term address (Value term address) (ResumableC (BaseError (ValueError term address)) (Eff m)) a
-> Evaluator term address (Value term address) m (Either (SomeError (BaseError (ValueError term address))) a) -> Evaluator term address (Value term address) m (Either (SomeError (BaseError (ValueError term address))) a)
runValueError = Evaluator . runResumable . runEvaluator runValueError = Evaluator . runResumable . runEvaluator
runValueErrorWith :: Carrier sig m runValueErrorWith :: (forall resume . BaseError (ValueError term address) resume -> Evaluator term address (Value term address) m resume)
=> (forall resume . BaseError (ValueError term address) resume -> Evaluator term address (Value term address) m resume) -> Evaluator term address (Value term address) (ResumableWithC (BaseError (ValueError term address)) m) a
-> Evaluator term address (Value term address) (ResumableWithC (BaseError (ValueError term address)) (Eff m)) a
-> Evaluator term address (Value term address) m a -> Evaluator term address (Value term address) m a
runValueErrorWith f = Evaluator . runResumableWith (runEvaluator . f) . runEvaluator runValueErrorWith f = Evaluator . runResumableWith (runEvaluator . f) . runEvaluator

View File

@ -87,10 +87,13 @@ instance Ord1 TypeError where
instance Show1 TypeError where liftShowsPrec _ _ = showsPrec instance Show1 TypeError where liftShowsPrec _ _ = showsPrec
runTypeError :: (Carrier sig m, Effect sig) => Evaluator term address value (ResumableC (BaseError TypeError) (Eff m)) a -> Evaluator term address value m (Either (SomeError (BaseError TypeError)) a) runTypeError :: Evaluator term address value (ResumableC (BaseError TypeError) m) a
-> Evaluator term address value m (Either (SomeError (BaseError TypeError)) a)
runTypeError = raiseHandler runResumable runTypeError = raiseHandler runResumable
runTypeErrorWith :: Carrier sig m => (forall resume . (BaseError TypeError) resume -> Evaluator term address value m resume) -> Evaluator term address value (ResumableWithC (BaseError TypeError) (Eff m)) a -> Evaluator term address value m a runTypeErrorWith :: (forall resume . (BaseError TypeError) resume -> Evaluator term address value m resume)
-> Evaluator term address value (ResumableWithC (BaseError TypeError) m) a
-> Evaluator term address value m a
runTypeErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f) runTypeErrorWith f = raiseHandler $ runResumableWith (runEvaluator . f)
@ -98,29 +101,27 @@ throwTypeError :: ( Member (Resumable (BaseError TypeError)) sig
, Member (Reader ModuleInfo) sig , Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> TypeError resume => TypeError resume
-> m resume -> m resume
throwTypeError = throwBaseError throwTypeError = throwBaseError
runTypeMap :: (Carrier sig m, Effect sig) runTypeMap :: Carrier sig m
=> Evaluator term address Type (StateC TypeMap (Eff m)) a => Evaluator term address Type (StateC TypeMap m) a
-> Evaluator term address Type m a -> Evaluator term address Type m a
runTypeMap = raiseHandler $ fmap snd . runState emptyTypeMap runTypeMap = raiseHandler $ fmap snd . runState emptyTypeMap
runTypes :: (Carrier sig m, Effect sig) runTypes :: Carrier sig m
=> Evaluator term address Type (ResumableC (BaseError TypeError) (Eff => Evaluator term address Type (ResumableC (BaseError TypeError)
(StateC TypeMap (Eff (StateC TypeMap m)) a
m)))) a
-> Evaluator term address Type m (Either (SomeError (BaseError TypeError)) a) -> Evaluator term address Type m (Either (SomeError (BaseError TypeError)) a)
runTypes = runTypeMap . runTypeError runTypes = runTypeMap . runTypeError
runTypesWith :: (Carrier sig m, Effect sig) runTypesWith :: Carrier sig m
=> (forall resume . (BaseError TypeError) resume -> Evaluator term address Type (StateC TypeMap (Eff m)) resume) => (forall resume . (BaseError TypeError) resume -> Evaluator term address Type (StateC TypeMap m) resume)
-> Evaluator term address Type (ResumableWithC (BaseError TypeError) (Eff -> Evaluator term address Type (ResumableWithC (BaseError TypeError)
(StateC TypeMap (Eff (StateC TypeMap
m)))) a m)) a
-> Evaluator term address Type m a -> Evaluator term address Type m a
runTypesWith with = runTypeMap . runTypeErrorWith with runTypesWith with = runTypeMap . runTypeErrorWith with
@ -132,7 +133,6 @@ emptyTypeMap = TypeMap Map.empty
modifyTypeMap :: ( Member (State TypeMap) sig modifyTypeMap :: ( Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> (Map.Map TName Type -> Map.Map TName Type) => (Map.Map TName Type -> Map.Map TName Type)
-> m () -> m ()
@ -141,7 +141,6 @@ modifyTypeMap f = modify (TypeMap . f . unTypeMap)
-- | Prunes substituted type variables -- | Prunes substituted type variables
prune :: ( Member (State TypeMap) sig prune :: ( Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> Type => Type
-> m Type -> m Type
@ -157,7 +156,6 @@ prune ty = pure ty
-- function is used in 'substitute' to prevent unification of infinite types -- function is used in 'substitute' to prevent unification of infinite types
occur :: ( Member (State TypeMap) sig occur :: ( Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> TName => TName
-> Type -> Type
@ -189,7 +187,6 @@ substitute :: ( Member (Reader ModuleInfo) sig
, Member (Resumable (BaseError TypeError)) sig , Member (Resumable (BaseError TypeError)) sig
, Member (State TypeMap) sig , Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> TName => TName
-> Type -> Type
@ -208,7 +205,6 @@ unify :: ( Member (Reader ModuleInfo) sig
, Member (Resumable (BaseError TypeError)) sig , Member (Resumable (BaseError TypeError)) sig
, Member (State TypeMap) sig , Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> Type => Type
-> Type -> Type
@ -256,35 +252,38 @@ instance ( Member (Allocator address) sig
, Show address , Show address
, Carrier sig m , Carrier sig m
) )
=> Carrier (Abstract.Function term address Type :+: sig) (FunctionC term address Type (Eff m)) where => Carrier (Abstract.Function term address Type :+: sig) (FunctionC term address Type m) where
ret = FunctionC . const . ret eff (R other) = FunctionC (eff (R (handleCoercible other)))
eff op = FunctionC (\ eval -> handleSum (eff . handleReader eval runFunctionC) (\case eff (L op) = runEvaluator $ do
Abstract.Function _ params body scope k -> runEvaluator $ do eval <- Evaluator . FunctionC $ ask
currentScope' <- currentScope case op of
currentFrame' <- currentFrame Abstract.Function _ params body scope k -> do
let frameLinks = Map.singleton Lexical (Map.singleton currentScope' currentFrame') currentScope' <- currentScope
frame <- newFrame scope frameLinks currentFrame' <- currentFrame
res <- withScopeAndFrame frame $ do let frameLinks = Map.singleton Lexical (Map.singleton currentScope' currentFrame')
tvars <- foldr (\ param rest -> do frame <- newFrame scope frameLinks
tvar <- Var <$> fresh res <- withScopeAndFrame frame $ do
slot <- lookupSlot (Declaration param) tvars <- foldr (\ param rest -> do
assign slot tvar tvar <- Var <$> fresh
(tvar :) <$> rest) (pure []) params slot <- lookupSlot (Declaration param)
-- TODO: We may still want to represent this as a closure and not a function type assign slot tvar
(zeroOrMoreProduct tvars :->) <$> catchReturn (runFunction (Evaluator . eval) (Evaluator (eval body))) (tvar :) <$> rest) (pure []) params
Evaluator (runFunctionC (k res) eval) -- TODO: We may still want to represent this as a closure and not a function type
(zeroOrMoreProduct tvars :->) <$> catchReturn (Evaluator (eval body))
Evaluator (k res)
Abstract.BuiltIn _ Print k -> Evaluator $ k (String :-> Unit)
Abstract.BuiltIn _ Show k -> Evaluator $ k (Object :-> String)
Abstract.Bind _ value k -> Evaluator $ k value
Abstract.Call op paramTypes k -> do
tvar <- fresh
let needed = zeroOrMoreProduct paramTypes :-> Var tvar
unified <- op `unify` needed
boxed <- case unified of
_ :-> ret -> pure ret
actual -> throwTypeError (UnificationError needed actual)
Evaluator (k boxed)
Abstract.BuiltIn _ Print k -> runFunctionC (k (String :-> Unit)) eval
Abstract.BuiltIn _ Show k -> runFunctionC (k (Object :-> String)) eval
Abstract.Bind _ value k -> runFunctionC (k value) eval
Abstract.Call op paramTypes k -> runEvaluator $ do
tvar <- fresh
let needed = zeroOrMoreProduct paramTypes :-> Var tvar
unified <- op `unify` needed
boxed <- case unified of
_ :-> ret -> pure ret
actual -> throwTypeError (UnificationError needed actual)
Evaluator $ runFunctionC (k boxed) eval) op)
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
@ -293,35 +292,29 @@ instance ( Member (Reader ModuleInfo) sig
, Member (State TypeMap) sig , Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Alternative m , Alternative m
, Monad m
) )
=> Carrier (Abstract.Boolean Type :+: sig) (BooleanC Type m) where => Carrier (Abstract.Boolean Type :+: sig) (BooleanC Type m) where
ret = BooleanC . ret eff (R other) = BooleanC . eff . handleCoercible $ other
eff = BooleanC . handleSum (eff . handleCoercible) (\case eff (L (Abstract.Boolean _ k)) = k Bool
Abstract.Boolean _ k -> runBooleanC (k Bool) eff (L (Abstract.AsBool t k)) = unify t Bool *> (k True <|> k False)
Abstract.AsBool t k -> unify t Bool *> (runBooleanC (k True) <|> runBooleanC (k False)))
instance ( Member (Abstract.Boolean Type) sig instance ( Member (Abstract.Boolean Type) sig
, Carrier sig m , Carrier sig m
, Alternative m , Alternative m
, Monad m
) )
=> Carrier (Abstract.While Type :+: sig) (WhileC Type m) where => Carrier (Abstract.While Type :+: sig) (WhileC Type m) where
ret = WhileC . ret eff (R other) = WhileC . eff . handleCoercible $ other
eff = WhileC . handleSum eff (L (Abstract.While cond body k)) = do
(eff . handleCoercible) cond' <- cond
(\ (Abstract.While cond body k) -> do ifthenelse cond' (body *> empty) (k Unit)
cond' <- runWhileC cond
ifthenelse cond' (runWhileC body *> empty) (runWhileC (k Unit)))
instance Carrier sig m instance Carrier sig m
=> Carrier (Abstract.Unit Type :+: sig) (UnitC Type m) where => Carrier (Abstract.Unit Type :+: sig) (UnitC Type m) where
ret = UnitC . ret eff (R other) = UnitC . eff . handleCoercible $ other
eff = UnitC . handleSum eff (L (Abstract.Unit k)) = k Unit
(eff . handleCoercible)
(\ (Abstract.Unit k) -> runUnitC (k Unit))
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -329,13 +322,11 @@ instance ( Member (Reader ModuleInfo) sig
, Member (State TypeMap) sig , Member (State TypeMap) sig
, Carrier sig m , Carrier sig m
, Alternative m , Alternative m
, Monad m
) )
=> Carrier (Abstract.String Type :+: sig) (StringC Type m) where => Carrier (Abstract.String Type :+: sig) (StringC Type m) where
ret = StringC . ret eff (R other) = StringC . eff . handleCoercible $ other
eff = StringC . handleSum (eff . handleCoercible) (\case eff (L (Abstract.String _ k)) = k String
Abstract.String _ k -> runStringC (k String) eff (L (Abstract.AsString t k)) = unify t String *> k ""
Abstract.AsString t k -> unify t String *> runStringC (k ""))
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -345,16 +336,16 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Numeric Type :+: sig) (NumericC Type m) where => Carrier (Abstract.Numeric Type :+: sig) (NumericC Type m) where
ret = NumericC . ret eff (R other) = NumericC . eff . handleCoercible $ other
eff = NumericC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Integer _ k -> runNumericC (k Int) Abstract.Integer _ k -> k Int
Abstract.Float _ k -> runNumericC (k Float) Abstract.Float _ k -> k Float
Abstract.Rational _ k -> runNumericC (k Rational) Abstract.Rational _ k -> k Rational
Abstract.LiftNumeric _ t k -> unify (Int :+ Float :+ Rational) t >>= runNumericC . k Abstract.LiftNumeric _ t k -> unify (Int :+ Float :+ Rational) t >>= k
Abstract.LiftNumeric2 _ left right k -> case (left, right) of Abstract.LiftNumeric2 _ left right k -> case (left, right) of
(Float, Int) -> runNumericC (k Float) (Float, Int) -> k Float
(Int, Float) -> runNumericC (k Float) (Int, Float) -> k Float
_ -> unify left right >>= runNumericC . k) _ -> unify left right >>= k
instance ( Member (Reader ModuleInfo) sig instance ( Member (Reader ModuleInfo) sig
, Member (Reader Span) sig , Member (Reader Span) sig
@ -364,19 +355,19 @@ instance ( Member (Reader ModuleInfo) sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Bitwise Type :+: sig) (BitwiseC Type m) where => Carrier (Abstract.Bitwise Type :+: sig) (BitwiseC Type m) where
ret = BitwiseC . ret eff (R other) = BitwiseC . eff . handleCoercible $ other
eff = BitwiseC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
CastToInteger t k -> unify t (Int :+ Float :+ Rational) >> runBitwiseC (k Int) CastToInteger t k -> unify t (Int :+ Float :+ Rational) *> k Int
LiftBitwise _ t k -> unify t Int >>= runBitwiseC . k LiftBitwise _ t k -> unify t Int >>= k
LiftBitwise2 _ t1 t2 k -> unify Int t1 >>= unify t2 >>= runBitwiseC . k LiftBitwise2 _ t1 t2 k -> unify Int t1 >>= unify t2 >>= k
UnsignedRShift t1 t2 k -> unify Int t2 *> unify Int t1 >>= runBitwiseC . k) UnsignedRShift t1 t2 k -> unify Int t2 *> unify Int t1 >>= k
instance ( Carrier sig m ) => Carrier (Abstract.Object address Type :+: sig) (ObjectC address Type m) where instance ( Carrier sig m ) => Carrier (Abstract.Object address Type :+: sig) (ObjectC address Type m) where
ret = ObjectC . ret eff (R other) = ObjectC . eff . handleCoercible $ other
eff = ObjectC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Abstract.Object _ k -> runObjectC (k Object) Abstract.Object _ k -> k Object
Abstract.ScopedEnvironment _ k -> runObjectC (k Nothing) Abstract.ScopedEnvironment _ k -> k Nothing
Abstract.Klass _ _ k -> runObjectC (k Object)) Abstract.Klass _ _ k -> k Object
instance ( Member Fresh sig instance ( Member Fresh sig
, Member (Reader ModuleInfo) sig , Member (Reader ModuleInfo) sig
@ -387,21 +378,19 @@ instance ( Member Fresh sig
, Monad m , Monad m
) )
=> Carrier (Abstract.Array Type :+: sig) (ArrayC Type m) where => Carrier (Abstract.Array Type :+: sig) (ArrayC Type m) where
ret = ArrayC . ret eff (R other) = ArrayC . eff . handleCoercible $ other
eff = ArrayC . handleSum (eff . handleCoercible) (\case eff (L (Abstract.Array fieldTypes k)) = do
Abstract.Array fieldTypes k -> do var <- fresh
var <- fresh fieldType <- foldr (\ t1 -> (unify t1 =<<)) (pure (Var var)) fieldTypes
fieldType <- foldr (\ t1 -> (unify t1 =<<)) (pure (Var var)) fieldTypes k (Array fieldType)
runArrayC (k (Array fieldType)) eff (L (Abstract.AsArray t k)) = do
Abstract.AsArray t k -> do field <- fresh
field <- fresh unify t (Array (Var field)) >> k mempty
unify t (Array (Var field)) >> runArrayC (k mempty))
instance ( Carrier sig m ) => Carrier (Abstract.Hash Type :+: sig) (HashC Type m) where instance ( Carrier sig m ) => Carrier (Abstract.Hash Type :+: sig) (HashC Type m) where
ret = HashC . ret eff (R other) = HashC . eff . handleCoercible $ other
eff = HashC . handleSum (eff . handleCoercible) (\case eff (L (Abstract.Hash t k)) = k (Hash t)
Abstract.Hash t k -> runHashC (k (Hash t)) eff (L (Abstract.KvPair t1 t2 k)) = k (t1 :* t2)
Abstract.KvPair t1 t2 k -> runHashC (k (t1 :* t2)))
instance AbstractHole Type where instance AbstractHole Type where

View File

@ -49,7 +49,7 @@ topologicalSort = go . Class.toAdjacencyMap . G.transpose . unGraph
. traverse_ visit . traverse_ visit
. A.vertexList . A.vertexList
$ graph $ graph
where visit :: (Member (State (Visited v)) sig, Carrier sig m, Monad m) => v -> m () where visit :: (Member (State (Visited v)) sig, Carrier sig m) => v -> m ()
visit v = do visit v = do
isMarked <- Set.member v . visitedVertices <$> get isMarked <- Set.member v . visitedVertices <$> get
if isMarked then if isMarked then

View File

@ -58,7 +58,7 @@ newtype ProjectException
= FileNotFound FilePath = FileNotFound FilePath
deriving (Show, Eq, Typeable, Exception) deriving (Show, Eq, Typeable, Exception)
readFile :: (Member (Error SomeException) sig, Applicative m, Carrier sig m) readFile :: (Member (Error SomeException) sig, Carrier sig m)
=> Project => Project
-> File -> File
-> m (Maybe Blob) -> m (Maybe Blob)

View File

@ -47,13 +47,10 @@ instance Effect (Diff term1 term2 diff) where
handle state handler = coerce . fmap (handler . (<$ state)) handle state handler = coerce . fmap (handler . (<$ state))
newtype Algorithm term1 term2 diff m a = Algorithm { runAlgorithm :: Eff m a } newtype Algorithm term1 term2 diff m a = Algorithm { runAlgorithm :: m a }
deriving (Applicative, Functor, Monad) deriving (Applicative, Alternative, Functor, Monad)
deriving instance (Carrier sig m, Member NonDet sig) => Alternative (Algorithm term1 term2 diff m)
instance Carrier sig m => Carrier sig (Algorithm term1 term2 diff m) where instance Carrier sig m => Carrier sig (Algorithm term1 term2 diff m) where
ret = Algorithm . ret
eff = Algorithm . eff . handleCoercible eff = Algorithm . eff . handleCoercible
@ -61,7 +58,7 @@ instance Carrier sig m => Carrier sig (Algorithm term1 term2 diff m) where
-- | Diff two terms without specifying the algorithm to be used. -- | Diff two terms without specifying the algorithm to be used.
diff :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> m diff diff :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> m diff
diff a1 a2 = send (Diff a1 a2 ret) diff a1 a2 = send (Diff a1 a2 pure)
-- | Diff a These of terms without specifying the algorithm to be used. -- | Diff a These of terms without specifying the algorithm to be used.
diffThese :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => These term1 term2 -> Algorithm term1 term2 diff m diff diffThese :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => These term1 term2 -> Algorithm term1 term2 diff m diff
@ -76,30 +73,30 @@ diffMaybe _ _ = pure Nothing
-- | Diff two terms linearly. -- | Diff two terms linearly.
linearly :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> Algorithm term1 term2 diff m diff linearly :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> Algorithm term1 term2 diff m diff
linearly f1 f2 = send (Linear f1 f2 ret) linearly f1 f2 = send (Linear f1 f2 pure)
-- | Diff two terms using RWS. -- | Diff two terms using RWS.
byRWS :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => [term1] -> [term2] -> Algorithm term1 term2 diff m [diff] byRWS :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => [term1] -> [term2] -> Algorithm term1 term2 diff m [diff]
byRWS as1 as2 = send (RWS as1 as2 ret) byRWS as1 as2 = send (RWS as1 as2 pure)
-- | Delete a term. -- | Delete a term.
byDeleting :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> Algorithm term1 term2 diff m diff byDeleting :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> Algorithm term1 term2 diff m diff
byDeleting a1 = sendDiff (Delete a1 ret) byDeleting a1 = sendDiff (Delete a1 pure)
-- | Insert a term. -- | Insert a term.
byInserting :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term2 -> Algorithm term1 term2 diff m diff byInserting :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term2 -> Algorithm term1 term2 diff m diff
byInserting a2 = sendDiff (Insert a2 ret) byInserting a2 = sendDiff (Insert a2 pure)
-- | Replace one term with another. -- | Replace one term with another.
byReplacing :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> Algorithm term1 term2 diff m diff byReplacing :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => term1 -> term2 -> Algorithm term1 term2 diff m diff
byReplacing a1 a2 = send (Replace a1 a2 ret) byReplacing a1 a2 = send (Replace a1 a2 pure)
sendDiff :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => Diff term1 term2 diff (Eff m) (Eff m a) -> Algorithm term1 term2 diff m a sendDiff :: (Carrier sig m, Member (Diff term1 term2 diff) sig) => Diff term1 term2 diff m (m a) -> Algorithm term1 term2 diff m a
sendDiff = Algorithm . send sendDiff = Algorithm . send
-- | Diff two terms based on their 'Diffable' instances, performing substructural comparisons iff the initial comparison fails. -- | Diff two terms based on their 'Diffable' instances, performing substructural comparisons iff the initial comparison fails.
algorithmForTerms :: (Carrier sig m, Diffable syntax, Member (Diff (Term syntax ann1) (Term syntax ann2) (Diff.Diff syntax ann1 ann2)) sig, Member NonDet sig) algorithmForTerms :: (Carrier sig m, Diffable syntax, Member (Diff (Term syntax ann1) (Term syntax ann2) (Diff.Diff syntax ann1 ann2)) sig, Member NonDet sig, Alternative m)
=> Term syntax ann1 => Term syntax ann1
-> Term syntax ann2 -> Term syntax ann2
-> Algorithm (Term syntax ann1) (Term syntax ann2) (Diff.Diff syntax ann1 ann2) m (Diff.Diff syntax ann1 ann2) -> Algorithm (Term syntax ann1) (Term syntax ann2) (Diff.Diff syntax ann1 ann2) m (Diff.Diff syntax ann1 ann2)
@ -142,12 +139,12 @@ instance Alternative Equivalence where
-- | A type class for determining what algorithm to use for diffing two terms. -- | A type class for determining what algorithm to use for diffing two terms.
class Diffable f where class Diffable f where
-- | Construct an algorithm to diff a pair of @f@s populated with disjoint terms. -- | Construct an algorithm to diff a pair of @f@s populated with disjoint terms.
algorithmFor :: (Carrier sig m, Member (Diff term1 term2 diff) sig, Member NonDet sig) algorithmFor :: (Alternative m, Carrier sig m, Member (Diff term1 term2 diff) sig, Member NonDet sig)
=> f term1 => f term1
-> f term2 -> f term2
-> Algorithm term1 term2 diff m (f diff) -> Algorithm term1 term2 diff m (f diff)
default default
algorithmFor :: (Carrier sig m, Generic1 f, GDiffable (Rep1 f), Member (Diff term1 term2 diff) sig, Member NonDet sig) algorithmFor :: (Alternative m, Carrier sig m, Generic1 f, GDiffable (Rep1 f), Member (Diff term1 term2 diff) sig, Member NonDet sig)
=> f term1 => f term1
-> f term2 -> f term2
-> Algorithm term1 term2 diff m (f diff) -> Algorithm term1 term2 diff m (f diff)
@ -190,7 +187,7 @@ class Diffable f where
default comparableTo :: (Generic1 f, GDiffable (Rep1 f)) => f term1 -> f term2 -> Bool default comparableTo :: (Generic1 f, GDiffable (Rep1 f)) => f term1 -> f term2 -> Bool
comparableTo = genericComparableTo comparableTo = genericComparableTo
genericAlgorithmFor :: (Carrier sig m, Generic1 f, GDiffable (Rep1 f), Member (Diff term1 term2 diff) sig, Member NonDet sig) genericAlgorithmFor :: (Alternative m, Carrier sig m, Generic1 f, GDiffable (Rep1 f), Member (Diff term1 term2 diff) sig, Member NonDet sig)
=> f term1 => f term1
-> f term2 -> f term2
-> Algorithm term1 term2 diff m (f diff) -> Algorithm term1 term2 diff m (f diff)
@ -238,7 +235,7 @@ instance Diffable NonEmpty where
-- | A generic type class for diffing two terms defined by the Generic1 interface. -- | A generic type class for diffing two terms defined by the Generic1 interface.
class GDiffable f where class GDiffable f where
galgorithmFor :: (Carrier sig m, Member (Diff term1 term2 diff) sig, Member NonDet sig) => f term1 -> f term2 -> Algorithm term1 term2 diff m (f diff) galgorithmFor :: (Alternative m, Carrier sig m, Member (Diff term1 term2 diff) sig, Member NonDet sig) => f term1 -> f term2 -> Algorithm term1 term2 diff m (f diff)
gtryAlignWith :: Alternative g => (These a1 a2 -> g b) -> f a1 -> f a2 -> g (f b) gtryAlignWith :: Alternative g => (These a1 a2 -> g b) -> f a1 -> f a2 -> g (f b)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances #-}
module Diffing.Interpreter module Diffing.Interpreter
( diffTerms ( diffTerms
, diffTermPair , diffTermPair
@ -7,6 +7,7 @@ module Diffing.Interpreter
import Control.Effect import Control.Effect
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Cull
import Control.Effect.NonDet import Control.Effect.NonDet
import Control.Effect.Sum import Control.Effect.Sum
import qualified Data.Diff as Diff import qualified Data.Diff as Diff
@ -36,18 +37,18 @@ diffTermPair = these Diff.deleting Diff.inserting diffTerms
-- | Run an 'Algorithm' to completion in an 'Alternative' context using the supplied comparability & equivalence relations. -- | Run an 'Algorithm' to completion in an 'Alternative' context using the supplied comparability & equivalence relations.
runDiff :: (Alternative m, Carrier sig m, Diffable syntax, Eq1 syntax, Member NonDet sig, Monad m, Traversable syntax) runDiff :: Algorithm
=> Algorithm
(Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann))
(Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann))
(Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann))
(DiffC (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) m) (DiffC (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) m)
result result
-> m result -> m result
runDiff = runDiffC . interpret . runAlgorithm runDiff = runDiffC . runAlgorithm
newtype DiffC term1 term2 diff m a = DiffC { runDiffC :: m a } newtype DiffC term1 term2 diff m a = DiffC { runDiffC :: m a }
deriving (Alternative, Applicative, Functor, Monad, MonadIO)
instance ( Alternative m instance ( Alternative m
, Carrier sig m , Carrier sig m
@ -60,11 +61,11 @@ instance ( Alternative m
=> Carrier => Carrier
(Diff (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) :+: sig) (Diff (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) :+: sig)
(DiffC (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) m) where (DiffC (Term syntax (FeatureVector, ann)) (Term syntax (FeatureVector, ann)) (Diff.Diff syntax (FeatureVector, ann) (FeatureVector, ann)) m) where
ret = DiffC . ret eff (L op) = case op of
eff = DiffC . handleSum (eff . handleCoercible) (\case Diff t1 t2 k -> runDiff (algorithmForTerms t1 t2) <|> pure (Diff.replacing t1 t2) >>= k
Diff t1 t2 k -> runDiff (algorithmForTerms t1 t2) <|> pure (Diff.replacing t1 t2) >>= runDiffC . k Linear (Term (In ann1 f1)) (Term (In ann2 f2)) k -> Diff.merge (ann1, ann2) <$> tryAlignWith (runDiff . diffThese) f1 f2 >>= k
Linear (Term (In ann1 f1)) (Term (In ann2 f2)) k -> Diff.merge (ann1, ann2) <$> tryAlignWith (runDiff . diffThese) f1 f2 >>= runDiffC . k RWS as bs k -> traverse (runDiff . diffThese) (rws comparableTerms equivalentTerms as bs) >>= k
RWS as bs k -> traverse (runDiff . diffThese) (rws comparableTerms equivalentTerms as bs) >>= runDiffC . k Delete a k -> k (Diff.deleting a)
Delete a k -> runDiffC (k (Diff.deleting a)) Insert b k -> k (Diff.inserting b)
Insert b k -> runDiffC (k (Diff.inserting b)) Replace a b k -> k (Diff.replacing a b)
Replace a b k -> runDiffC (k (Diff.replacing a b))) eff (R other) = DiffC . eff . handleCoercible $ other

View File

@ -19,7 +19,7 @@ import Data.Reprinting.Token
import Data.Reprinting.Scope import Data.Reprinting.Scope
-- | Default printing pipeline for JSON. -- | Default printing pipeline for JSON.
defaultJSONPipeline :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) defaultJSONPipeline :: (Member (Error TranslationError) sig, Carrier sig m)
=> ProcessT m Fragment Splice => ProcessT m Fragment Splice
defaultJSONPipeline defaultJSONPipeline
= printingJSON = printingJSON
@ -56,7 +56,7 @@ defaultBeautyOpts :: JSONBeautyOpts
defaultBeautyOpts = JSONBeautyOpts 2 False defaultBeautyOpts = JSONBeautyOpts 2 False
-- | Produce JSON with configurable whitespace and layout. -- | Produce JSON with configurable whitespace and layout.
beautifyingJSON :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) beautifyingJSON :: (Member (Error TranslationError) sig, Carrier sig m)
=> JSONBeautyOpts -> ProcessT m Fragment Splice => JSONBeautyOpts -> ProcessT m Fragment Splice
beautifyingJSON _ = repeatedly (await >>= step) where beautifyingJSON _ = repeatedly (await >>= step) where
step (Defer el cs) = lift (throwError (NoTranslation el cs)) step (Defer el cs) = lift (throwError (NoTranslation el cs))
@ -70,7 +70,7 @@ beautifyingJSON _ = repeatedly (await >>= step) where
_ -> emit txt _ -> emit txt
-- | Produce whitespace minimal JSON. -- | Produce whitespace minimal JSON.
minimizingJSON :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) minimizingJSON :: (Member (Error TranslationError) sig, Carrier sig m)
=> ProcessT m Fragment Splice => ProcessT m Fragment Splice
minimizingJSON = repeatedly (await >>= step) where minimizingJSON = repeatedly (await >>= step) where
step (Defer el cs) = lift (throwError (NoTranslation el cs)) step (Defer el cs) = lift (throwError (NoTranslation el cs))

View File

@ -14,10 +14,10 @@ import Data.Reprinting.Scope
import Data.Reprinting.Operator import Data.Reprinting.Operator
-- | Print Python syntax. -- | Print Python syntax.
printingPython :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) => ProcessT m Fragment Splice printingPython :: (Member (Error TranslationError) sig, Carrier sig m) => ProcessT m Fragment Splice
printingPython = repeatedly (await >>= step) printingPython = repeatedly (await >>= step)
step :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) => Fragment -> PlanT k Splice m () step :: (Member (Error TranslationError) sig, Carrier sig m) => Fragment -> PlanT k Splice m ()
step (Verbatim txt) = emit txt step (Verbatim txt) = emit txt
step (New _ _ txt) = emit txt step (New _ _ txt) = emit txt
step (Defer el cs) = case (el, cs) of step (Defer el cs) = case (el, cs) of

View File

@ -14,10 +14,10 @@ import Data.Reprinting.Splice
import Data.Reprinting.Token as Token import Data.Reprinting.Token as Token
-- | Print Ruby syntax. -- | Print Ruby syntax.
printingRuby :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) => ProcessT m Fragment Splice printingRuby :: (Member (Error TranslationError) sig, Carrier sig m) => ProcessT m Fragment Splice
printingRuby = repeatedly (await >>= step) printingRuby = repeatedly (await >>= step)
step :: (Member (Error TranslationError) sig, Carrier sig m, Monad m) => Fragment -> PlanT k Splice m () step :: (Member (Error TranslationError) sig, Carrier sig m) => Fragment -> PlanT k Splice m ()
step (Verbatim txt) = emit txt step (Verbatim txt) = emit txt
step (New _ _ txt) = emit txt step (New _ _ txt) = emit txt
step (Defer el cs) = case (el, cs) of step (Defer el cs) = case (el, cs) of

View File

@ -18,7 +18,7 @@ import Data.Patch
import Data.String (IsString (..)) import Data.String (IsString (..))
import Data.Term import Data.Term
import Prologue import Prologue
import Semantic.Api.Helpers import Semantic.Api.Bridge
import Semantic.Api.V1.CodeAnalysisPB import Semantic.Api.V1.CodeAnalysisPB
import qualified Data.Text as T import qualified Data.Text as T
@ -27,9 +27,8 @@ import qualified Data.Text as T
renderTreeGraph :: (Ord vertex, Recursive t, ToTreeGraph vertex (Base t)) => t -> Graph vertex renderTreeGraph :: (Ord vertex, Recursive t, ToTreeGraph vertex (Base t)) => t -> Graph vertex
renderTreeGraph = simplify . runGraph . cata toTreeGraph renderTreeGraph = simplify . runGraph . cata toTreeGraph
runGraph :: Eff (ReaderC (Graph vertex) runGraph :: ReaderC (Graph vertex)
(Eff (FreshC (FreshC VoidC) (Graph vertex)
(Eff VoidC)))) (Graph vertex)
-> Graph vertex -> Graph vertex
runGraph = run . runFresh . runReader mempty runGraph = run . runFresh . runReader mempty
@ -54,7 +53,7 @@ diffStyle name = (defaultStyle (fromString . show . diffVertexId))
vertexAttributes _ = [] vertexAttributes _ = []
class ToTreeGraph vertex t | t -> vertex where class ToTreeGraph vertex t | t -> vertex where
toTreeGraph :: (Member Fresh sig, Member (Reader (Graph vertex)) sig, Carrier sig m, Monad m) => t (m (Graph vertex)) -> m (Graph vertex) toTreeGraph :: (Member Fresh sig, Member (Reader (Graph vertex)) sig, Carrier sig m) => t (m (Graph vertex)) -> m (Graph vertex)
instance (ConstructorName syntax, Foldable syntax) => instance (ConstructorName syntax, Foldable syntax) =>
ToTreeGraph TermVertex (TermF syntax Location) where ToTreeGraph TermVertex (TermF syntax Location) where
@ -65,14 +64,13 @@ instance (ConstructorName syntax, Foldable syntax) =>
, Member Fresh sig , Member Fresh sig
, Member (Reader (Graph TermVertex)) sig , Member (Reader (Graph TermVertex)) sig
, Carrier sig m , Carrier sig m
, Monad m
) )
=> TermF syntax Location (m (Graph TermVertex)) => TermF syntax Location (m (Graph TermVertex))
-> m (Graph TermVertex) -> m (Graph TermVertex)
termAlgebra (In ann syntax) = do termAlgebra (In ann syntax) = do
i <- fresh i <- fresh
parent <- ask parent <- ask
let root = vertex (TermVertex (fromIntegral i) (T.pack (constructorName syntax)) (spanToSpan (locationSpan ann))) let root = vertex $ TermVertex (fromIntegral i) (T.pack (constructorName syntax)) (converting #? locationSpan ann)
subGraph <- foldl' (\acc x -> overlay <$> acc <*> local (const root) x) (pure mempty) syntax subGraph <- foldl' (\acc x -> overlay <$> acc <*> local (const root) x) (pure mempty) syntax
pure (parent `connect` root `overlay` subGraph) pure (parent `connect` root `overlay` subGraph)
@ -91,13 +89,12 @@ instance (ConstructorName syntax, Foldable syntax) =>
graph <- local (const replace) (overlay <$> diffAlgebra t1 (Deleted (Just (DeletedTerm beforeName beforeSpan))) <*> diffAlgebra t2 (Inserted (Just (InsertedTerm afterName afterSpan)))) graph <- local (const replace) (overlay <$> diffAlgebra t1 (Deleted (Just (DeletedTerm beforeName beforeSpan))) <*> diffAlgebra t2 (Inserted (Just (InsertedTerm afterName afterSpan))))
pure (parent `connect` replace `overlay` graph) pure (parent `connect` replace `overlay` graph)
where where
ann a = spanToSpan (locationSpan a) ann a = converting #? locationSpan a
diffAlgebra :: diffAlgebra ::
( Foldable f ( Foldable f
, Member Fresh sig , Member Fresh sig
, Member (Reader (Graph DiffTreeVertex)) sig , Member (Reader (Graph DiffTreeVertex)) sig
, Carrier sig m , Carrier sig m
, Monad m
) => f (m (Graph DiffTreeVertex)) -> DiffTreeVertexDiffTerm -> m (Graph DiffTreeVertex) ) => f (m (Graph DiffTreeVertex)) -> DiffTreeVertexDiffTerm -> m (Graph DiffTreeVertex)
diffAlgebra syntax a = do diffAlgebra syntax a = do
i <- fresh i <- fresh

View File

@ -19,9 +19,8 @@ import Data.Reprinting.Scope
import qualified Data.Source as Source import qualified Data.Source as Source
type Translator type Translator
= Eff (StateC [Scope] = StateC [Scope]
( Eff (ErrorC TranslationError ( ErrorC TranslationError VoidC)
( Eff VoidC))))
contextualizing :: ProcessT Translator Token Fragment contextualizing :: ProcessT Translator Token Fragment
contextualizing = repeatedly $ await >>= \case contextualizing = repeatedly $ await >>= \case

View File

@ -27,7 +27,7 @@ data SomeAST where
withSomeAST :: (forall grammar . Show grammar => AST [] grammar -> a) -> SomeAST -> a withSomeAST :: (forall grammar . Show grammar => AST [] grammar -> a) -> SomeAST -> a
withSomeAST f (SomeAST ast) = f ast withSomeAST f (SomeAST ast) = f ast
astParseBlob :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m, Functor m) => Blob -> m SomeAST astParseBlob :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m) => Blob -> m SomeAST
astParseBlob blob@Blob{..} astParseBlob blob@Blob{..}
| Just (SomeASTParser parser) <- someASTParser blobLanguage = SomeAST <$> parse parser blob | Just (SomeASTParser parser) <- someASTParser blobLanguage = SomeAST <$> parse parser blob
| otherwise = noLanguageForBlob blobPath | otherwise = noLanguageForBlob blobPath

View File

@ -17,36 +17,36 @@ import Prologue
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
type ModuleC address value m type ModuleC address value m
= ErrorC (LoopControl value) (Eff = ErrorC (LoopControl value)
( ErrorC (Return value) (Eff ( ErrorC (Return value)
( ReaderC (CurrentScope address) (Eff ( ReaderC (CurrentScope address)
( ReaderC (CurrentFrame address) (Eff ( ReaderC (CurrentFrame address)
( DerefC address value (Eff ( DerefC address value
( AllocatorC address (Eff ( AllocatorC address
( ReaderC ModuleInfo (Eff ( ReaderC ModuleInfo
m))))))))))))) m))))))
type DomainC term address value m type DomainC term address value m
= FunctionC term address value (Eff = FunctionC term address value
( WhileC value (Eff ( WhileC value
( BooleanC value (Eff ( BooleanC value
( StringC value (Eff ( StringC value
( NumericC value (Eff ( NumericC value
( BitwiseC value (Eff ( BitwiseC value
( ObjectC address value (Eff ( ObjectC address value
( ArrayC value (Eff ( ArrayC value
( HashC value (Eff ( HashC value
( UnitC value (Eff ( UnitC value
( InterposeC (Resumable (BaseError (UnspecializedError address value))) (Eff ( InterposeC (Resumable (BaseError (UnspecializedError address value)))
m))))))))))))))))))))) m))))))))))
-- | Evaluate a list of modules with the prelude for the passed language available, and applying the passed function to every module. -- | Evaluate a list of modules with the prelude for the passed language available, and applying the passed function to every module.
evaluate :: ( Carrier outerSig outer evaluate :: ( Carrier outerSig outer
, derefSig ~ (Deref value :+: allocatorSig) , derefSig ~ (Deref value :+: allocatorSig)
, derefC ~ (DerefC address value (Eff allocatorC)) , derefC ~ (DerefC address value allocatorC)
, Carrier derefSig derefC , Carrier derefSig derefC
, allocatorSig ~ (Allocator address :+: Reader ModuleInfo :+: outerSig) , allocatorSig ~ (Allocator address :+: Reader ModuleInfo :+: outerSig)
, allocatorC ~ (AllocatorC address (Eff (ReaderC ModuleInfo (Eff outer)))) , allocatorC ~ (AllocatorC address (ReaderC ModuleInfo outer))
, Carrier allocatorSig allocatorC , Carrier allocatorSig allocatorC
, Effect outerSig , Effect outerSig
, Member Fresh outerSig , Member Fresh outerSig
@ -86,35 +86,25 @@ evaluate lang runModule modules = do
. runModule . runModule
runDomainEffects :: ( AbstractValue term address value (DomainC term address value m) runDomainEffects :: ( AbstractValue term address value (DomainC term address value m)
, Carrier sig m , unitC ~ UnitC value (InterposeC (Resumable (BaseError (UnspecializedError address value))) m)
, unitC ~ UnitC value (Eff (InterposeC (Resumable (BaseError (UnspecializedError address value))) (Eff m)))
, unitSig ~ (Unit value :+: Interpose (Resumable (BaseError (UnspecializedError address value))) :+: sig) , unitSig ~ (Unit value :+: Interpose (Resumable (BaseError (UnspecializedError address value))) :+: sig)
, Carrier unitSig unitC , hashC ~ HashC value unitC
, hashC ~ HashC value (Eff unitC)
, hashSig ~ (Abstract.Hash value :+: unitSig) , hashSig ~ (Abstract.Hash value :+: unitSig)
, Carrier hashSig hashC , arrayC ~ ArrayC value hashC
, arrayC ~ ArrayC value (Eff hashC)
, arraySig ~ (Abstract.Array value :+: hashSig) , arraySig ~ (Abstract.Array value :+: hashSig)
, Carrier arraySig arrayC , objectC ~ ObjectC address value arrayC
, objectC ~ ObjectC address value (Eff arrayC)
, objectSig ~ (Abstract.Object address value :+: arraySig) , objectSig ~ (Abstract.Object address value :+: arraySig)
, Carrier objectSig objectC , bitwiseC ~ BitwiseC value objectC
, bitwiseC ~ BitwiseC value (Eff objectC)
, bitwiseSig ~ (Abstract.Bitwise value :+: objectSig) , bitwiseSig ~ (Abstract.Bitwise value :+: objectSig)
, Carrier bitwiseSig bitwiseC , numericC ~ NumericC value bitwiseC
, numericC ~ NumericC value (Eff bitwiseC)
, numericSig ~ (Abstract.Numeric value :+: bitwiseSig) , numericSig ~ (Abstract.Numeric value :+: bitwiseSig)
, Carrier numericSig numericC , stringC ~ StringC value numericC
, stringC ~ StringC value (Eff numericC)
, stringSig ~ (Abstract.String value :+: numericSig) , stringSig ~ (Abstract.String value :+: numericSig)
, Carrier stringSig stringC , booleanC ~ BooleanC value stringC
, booleanC ~ BooleanC value (Eff stringC)
, booleanSig ~ (Boolean value :+: stringSig) , booleanSig ~ (Boolean value :+: stringSig)
, Carrier booleanSig booleanC , whileC ~ WhileC value booleanC
, whileC ~ WhileC value (Eff booleanC)
, whileSig ~ (While value :+: booleanSig) , whileSig ~ (While value :+: booleanSig)
, Carrier whileSig whileC , functionC ~ FunctionC term address value whileC
, functionC ~ FunctionC term address value (Eff whileC)
, functionSig ~ (Function term address value :+: whileSig) , functionSig ~ (Function term address value :+: whileSig)
, Carrier functionSig functionC , Carrier functionSig functionC
, HasPrelude lang , HasPrelude lang
@ -128,7 +118,6 @@ runDomainEffects :: ( AbstractValue term address value (DomainC term address val
, Member (Resumable (BaseError (AddressError address value))) sig , Member (Resumable (BaseError (AddressError address value))) sig
, Member (Resumable (BaseError (HeapError address))) sig , Member (Resumable (BaseError (HeapError address))) sig
, Member (Resumable (BaseError (ScopeError address))) sig , Member (Resumable (BaseError (ScopeError address))) sig
, Member (Resumable (BaseError (UnspecializedError address value))) sig
, Member (State (Heap address address value)) sig , Member (State (Heap address address value)) sig
, Member (State (ScopeGraph address)) sig , Member (State (ScopeGraph address)) sig
, Member Trace sig , Member Trace sig

114
src/Semantic/Api/Bridge.hs Normal file
View File

@ -0,0 +1,114 @@
{-# LANGUAGE FunctionalDependencies, LambdaCase #-}
module Semantic.Api.Bridge
( APIBridge (..)
, APIConvert (..)
, (#?)
) where
import Control.Lens
import qualified Data.Blob as Data
import qualified Data.Language as Data
import Data.Source (fromText, toText)
import qualified Data.Span as Data
import qualified Data.Text as T
import qualified Semantic.Api.LegacyTypes as Legacy
import qualified Semantic.Api.V1.CodeAnalysisPB as API
-- | An @APIBridge x y@ instance describes an isomorphism between @x@ and @y@.
-- This is suitable for types such as 'Pos' which are representationally equivalent
-- in their API, legacy, and native forms. All 'Lens' laws apply.
--
-- Foreign to native: @x^.bridging@
-- Native to foreign: @bridging # x@
-- Native to 'Just' foreign: @bridging #? x@.
-- 'Maybe' foreign to 'Maybe' native: @x >>= preview bridging@
class APIBridge api native | api -> native where
bridging :: Iso' api native
-- | An @APIConvert x y@ instance describes a partial isomorphism between @x@ and @y@.
-- This is suitable for types containing nested records therein, such as 'Span'.
-- (The isomorphism must be partial, given that a protobuf record can have Nothing
-- for all its fields, which means we cannot convert to a native format.)
--
-- Foreign to native: this is a type error, unless the native is a Monoid
-- Foreign to 'Maybe' native: @x^?converting@
-- Native to foreign: @converting # x@
-- Native to 'Just' foreign: @converting #? x@
class APIConvert api native | api -> native where
converting :: Prism' api native
-- | A helper function for turning 'bridging' around and
-- extracting 'Just' values from it.
(#?) :: AReview t s -> s -> Maybe t
rev #? item = item ^? re rev
infixr 8 #?
instance APIBridge Legacy.Position Data.Pos where
bridging = iso fromAPI toAPI where
toAPI Data.Pos{..} = Legacy.Position posLine posColumn
fromAPI Legacy.Position{..} = Data.Pos line column
instance APIBridge API.Position Data.Pos where
bridging = iso fromAPI toAPI where
toAPI Data.Pos{..} = API.Position (fromIntegral posLine) (fromIntegral posColumn)
fromAPI API.Position{..} = Data.Pos (fromIntegral line) (fromIntegral column)
instance APIConvert API.Span Data.Span where
converting = prism' toAPI fromAPI where
toAPI Data.Span{..} = API.Span (bridging #? spanStart) (bridging #? spanEnd)
fromAPI API.Span{..} = Data.Span <$> (start >>= preview bridging) <*> (end >>= preview bridging)
instance APIConvert Legacy.Span Data.Span where
converting = prism' toAPI fromAPI where
toAPI Data.Span{..} = Legacy.Span (bridging #? spanStart) (bridging #? spanEnd)
fromAPI Legacy.Span {..} = Data.Span <$> (start >>= preview bridging) <*> (end >>= preview bridging)
instance APIBridge API.Language Data.Language where
bridging = iso apiLanguageToLanguage languageToApiLanguage where
languageToApiLanguage :: Data.Language -> API.Language
languageToApiLanguage = \case
Data.Unknown -> API.Unknown
Data.Go -> API.Go
Data.Haskell -> API.Haskell
Data.Java -> API.Java
Data.JavaScript -> API.Javascript
Data.JSON -> API.Json
Data.JSX -> API.Jsx
Data.Markdown -> API.Markdown
Data.Python -> API.Python
Data.Ruby -> API.Ruby
Data.TypeScript -> API.Typescript
Data.PHP -> API.Php
apiLanguageToLanguage :: API.Language -> Data.Language
apiLanguageToLanguage = \case
API.Unknown -> Data.Unknown
API.Go -> Data.Go
API.Haskell -> Data.Haskell
API.Java -> Data.Java
API.Javascript -> Data.JavaScript
API.Json -> Data.JSON
API.Jsx -> Data.JSX
API.Markdown -> Data.Markdown
API.Python -> Data.Python
API.Ruby -> Data.Ruby
API.Typescript -> Data.TypeScript
API.Php -> Data.PHP
instance APIBridge API.Blob Data.Blob where
bridging = iso apiBlobToBlob blobToApiBlob where
blobToApiBlob Data.Blob{..} = API.Blob (toText blobSource) (T.pack blobPath) (bridging # blobLanguage)
apiBlobToBlob API.Blob{..} = Data.Blob (fromText content) (T.unpack path) (language ^. bridging)
instance APIConvert API.BlobPair Data.BlobPair where
converting = prism' blobPairToApiBlobPair apiBlobPairToBlobPair where
apiBlobPairToBlobPair (API.BlobPair (Just before) (Just after)) = Just $ Data.Diffing (before^.bridging) (after^.bridging)
apiBlobPairToBlobPair (API.BlobPair (Just before) Nothing) = Just $ Data.Deleting (before^.bridging)
apiBlobPairToBlobPair (API.BlobPair Nothing (Just after)) = Just $ Data.Inserting (after^.bridging)
apiBlobPairToBlobPair _ = Nothing
blobPairToApiBlobPair (Data.Diffing before after) = API.BlobPair (bridging #? before) (bridging #? after)
blobPairToApiBlobPair (Data.Inserting after) = API.BlobPair Nothing (bridging #? after)
blobPairToApiBlobPair (Data.Deleting before) = API.BlobPair (bridging #? before) Nothing

View File

@ -16,6 +16,7 @@ import Analysis.TOCSummary (HasDeclaration)
import Control.Effect import Control.Effect
import Control.Effect.Error import Control.Effect.Error
import Control.Exception import Control.Exception
import Control.Lens
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Data.Blob import Data.Blob
import Data.ByteString.Builder import Data.ByteString.Builder
@ -33,7 +34,7 @@ import Prologue
import Rendering.Graph import Rendering.Graph
import Rendering.JSON hiding (JSON) import Rendering.JSON hiding (JSON)
import qualified Rendering.JSON import qualified Rendering.JSON
import Semantic.Api.Helpers import Semantic.Api.Bridge
import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, BlobPair, Language(..)) import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, BlobPair, Language(..))
import Semantic.Task as Task import Semantic.Task as Task
import Semantic.Telemetry as Stat import Semantic.Telemetry as Stat
@ -75,7 +76,7 @@ diffGraph blobs = DiffTreeGraphResponse . V.fromList . toList <$> distributeFor
pure (DiffTreeFileGraph path lang mempty mempty (V.fromList [ParseError (T.pack (show e))])) pure (DiffTreeFileGraph path lang mempty mempty (V.fromList [ParseError (T.pack (show e))]))
where where
path = T.pack $ pathForBlobPair blobPair path = T.pack $ pathForBlobPair blobPair
lang = languageToApiLanguage $ languageForBlobPair blobPair lang = bridging # languageForBlobPair blobPair
render :: (Foldable syntax, Functor syntax, ConstructorName syntax, Applicative m) => BlobPair -> Diff syntax Location Location -> m DiffTreeFileGraph render :: (Foldable syntax, Functor syntax, ConstructorName syntax, Applicative m) => BlobPair -> Diff syntax Location Location -> m DiffTreeFileGraph
render _ diff = render _ diff =
@ -124,7 +125,7 @@ diffTerms blobs terms = time "diff" languageTag $ do
diff <$ writeStat (Stat.count "diff.nodes" (bilength diff) languageTag) diff <$ writeStat (Stat.count "diff.nodes" (bilength diff) languageTag)
where languageTag = languageTagForBlobPair blobs where languageTag = languageTagForBlobPair blobs
doParse :: (Member (Error SomeException) sig, Member Distribute sig, Member Task sig, Carrier sig m, Monad m) doParse :: (Member (Error SomeException) sig, Member Distribute sig, Member Task sig, Carrier sig m)
=> BlobPair -> Decorate m Location ann -> m (SomeTermPair TermPairConstraints ann) => BlobPair -> Decorate m Location ann -> m (SomeTermPair TermPairConstraints ann)
doParse blobPair decorate = case languageForBlobPair blobPair of doParse blobPair decorate = case languageForBlobPair blobPair of
Go -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse goParser blob >>= decorate blob) Go -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse goParser blob >>= decorate blob)

View File

@ -1,88 +0,0 @@
{-# LANGUAGE LambdaCase #-}
module Semantic.Api.Helpers
( spanToSpan
, spanToLegacySpan
, toChangeType
, languageToApiLanguage
, apiSpanToSpan
, apiLanguageToLanguage
, apiBlobsToBlobs
, apiBlobToBlob
, apiBlobPairsToBlobPairs
, apiBlobPairToBlobPair
) where
import qualified Data.Blob as Data
import qualified Data.Language as Data
import Data.Source (fromText)
import qualified Data.Span as Data
import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Semantic.Api.LegacyTypes as Legacy
import qualified Semantic.Api.V1.CodeAnalysisPB as API
spanToSpan :: Data.Span -> Maybe API.Span
spanToSpan Data.Span{..} = Just $ API.Span (toPos spanStart) (toPos spanEnd)
where toPos Data.Pos{..} = Just $ API.Position (fromIntegral posLine) (fromIntegral posColumn)
spanToLegacySpan :: Data.Span -> Maybe Legacy.Span
spanToLegacySpan Data.Span{..} = Just $ Legacy.Span (toPos spanStart) (toPos spanEnd)
where toPos Data.Pos{..} = Just $ Legacy.Position posLine posColumn
apiSpanToSpan :: Maybe API.Span -> Data.Span
apiSpanToSpan (Just API.Span{..}) = Data.Span (toPos start) (toPos end)
where toPos (Just API.Position{..}) = Data.Pos (fromIntegral line) (fromIntegral column)
toPos Nothing = Data.Pos 1 1
apiSpanToSpan Nothing = Data.emptySpan
toChangeType :: T.Text -> API.ChangeType
toChangeType = \case
"added" -> API.Added
"modified" -> API.Modified
"removed" -> API.Removed
_ -> API.None
languageToApiLanguage :: Data.Language -> API.Language
languageToApiLanguage = \case
Data.Unknown -> API.Unknown
Data.Go -> API.Go
Data.Haskell -> API.Haskell
Data.Java -> API.Java
Data.JavaScript -> API.Javascript
Data.JSON -> API.Json
Data.JSX -> API.Jsx
Data.Markdown -> API.Markdown
Data.Python -> API.Python
Data.Ruby -> API.Ruby
Data.TypeScript -> API.Typescript
Data.PHP -> API.Php
apiLanguageToLanguage :: API.Language -> Data.Language
apiLanguageToLanguage = \case
API.Unknown -> Data.Unknown
API.Go -> Data.Go
API.Haskell -> Data.Haskell
API.Java -> Data.Java
API.Javascript -> Data.JavaScript
API.Json -> Data.JSON
API.Jsx -> Data.JSX
API.Markdown -> Data.Markdown
API.Python -> Data.Python
API.Ruby -> Data.Ruby
API.Typescript -> Data.TypeScript
API.Php -> Data.PHP
apiBlobsToBlobs :: V.Vector API.Blob -> [Data.Blob]
apiBlobsToBlobs = V.toList . fmap apiBlobToBlob
apiBlobToBlob :: API.Blob -> Data.Blob
apiBlobToBlob API.Blob{..} = Data.Blob (fromText content) (T.unpack path) (apiLanguageToLanguage language)
apiBlobPairsToBlobPairs :: V.Vector API.BlobPair -> [Data.BlobPair]
apiBlobPairsToBlobPairs = V.toList . fmap apiBlobPairToBlobPair
apiBlobPairToBlobPair :: API.BlobPair -> Data.BlobPair
apiBlobPairToBlobPair (API.BlobPair (Just before) (Just after)) = Data.Diffing (apiBlobToBlob before) (apiBlobToBlob after)
apiBlobPairToBlobPair (API.BlobPair (Just before) Nothing) = Data.Deleting (apiBlobToBlob before)
apiBlobPairToBlobPair (API.BlobPair Nothing (Just after)) = Data.Inserting (apiBlobToBlob after)
apiBlobPairToBlobPair _ = Prelude.error "Expected BlobPair to have either 'before' and/or 'after'."

View File

@ -10,6 +10,7 @@ import Prelude hiding (span)
import Control.Effect import Control.Effect
import Control.Effect.Error import Control.Effect.Error
import Control.Exception import Control.Exception
import Control.Lens
import Data.Blob import Data.Blob
import Data.ByteString.Builder import Data.ByteString.Builder
import Data.Location import Data.Location
@ -20,7 +21,7 @@ import qualified Data.Vector as V
import Data.Text (pack) import Data.Text (pack)
import Parsing.Parser import Parsing.Parser
import Prologue import Prologue
import Semantic.Api.Helpers import Semantic.Api.Bridge
import qualified Semantic.Api.LegacyTypes as Legacy import qualified Semantic.Api.LegacyTypes as Legacy
import Semantic.Api.Terms (ParseEffects, doParse) import Semantic.Api.Terms (ParseEffects, doParse)
import Semantic.Api.V1.CodeAnalysisPB hiding (Blob) import Semantic.Api.V1.CodeAnalysisPB hiding (Blob)
@ -32,7 +33,7 @@ import Tags.Tagging
legacyParseSymbols :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m Legacy.ParseTreeSymbolResponse legacyParseSymbols :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m Legacy.ParseTreeSymbolResponse
legacyParseSymbols blobs = Legacy.ParseTreeSymbolResponse <$> distributeFoldMap go blobs legacyParseSymbols blobs = Legacy.ParseTreeSymbolResponse <$> distributeFoldMap go blobs
where where
go :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m, Monad m) => Blob -> m [Legacy.File] go :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m) => Blob -> m [Legacy.File]
go blob@Blob{..} = (doParse blob >>= withSomeTerm (renderToSymbols blob)) `catchError` (\(SomeException _) -> pure (pure emptyFile)) go blob@Blob{..} = (doParse blob >>= withSomeTerm (renderToSymbols blob)) `catchError` (\(SomeException _) -> pure (pure emptyFile))
where emptyFile = Legacy.File (pack blobPath) (pack (show blobLanguage)) [] where emptyFile = Legacy.File (pack blobPath) (pack (show blobLanguage)) []
@ -48,7 +49,7 @@ legacyParseSymbols blobs = Legacy.ParseTreeSymbolResponse <$> distributeFoldMap
{ symbolName = name { symbolName = name
, symbolKind = kind , symbolKind = kind
, symbolLine = fromMaybe mempty line , symbolLine = fromMaybe mempty line
, symbolSpan = spanToLegacySpan span , symbolSpan = converting #? span
} }
parseSymbolsBuilder :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m Builder parseSymbolsBuilder :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m Builder
@ -57,16 +58,16 @@ parseSymbolsBuilder blobs = parseSymbols blobs >>= serialize JSON
parseSymbols :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m ParseTreeSymbolResponse parseSymbols :: (Member Distribute sig, ParseEffects sig m, Traversable t) => t Blob -> m ParseTreeSymbolResponse
parseSymbols blobs = ParseTreeSymbolResponse . V.fromList . toList <$> distributeFor blobs go parseSymbols blobs = ParseTreeSymbolResponse . V.fromList . toList <$> distributeFor blobs go
where where
go :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m, Monad m) => Blob -> m File go :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m) => Blob -> m File
go blob@Blob{..} = (doParse blob >>= withSomeTerm (renderToSymbols blob)) `catchError` (\(SomeException e) -> pure $ errorFile (show e)) go blob@Blob{..} = (doParse blob >>= withSomeTerm (renderToSymbols blob)) `catchError` (\(SomeException e) -> pure $ errorFile (show e))
where where
errorFile e = File (pack blobPath) (languageToApiLanguage blobLanguage) mempty (V.fromList [ParseError (T.pack e)]) errorFile e = File (pack blobPath) (bridging # blobLanguage) mempty (V.fromList [ParseError (T.pack e)])
renderToSymbols :: (IsTaggable f, Applicative m) => Blob -> Term f Location -> m File renderToSymbols :: (IsTaggable f, Applicative m) => Blob -> Term f Location -> m File
renderToSymbols blob@Blob{..} term = pure $ either (errorFile . show) (tagsToFile blob) (runTagging blob term) renderToSymbols blob@Blob{..} term = pure $ either (errorFile . show) (tagsToFile blob) (runTagging blob term)
tagsToFile :: Blob -> [Tag] -> File tagsToFile :: Blob -> [Tag] -> File
tagsToFile Blob{..} tags = File (pack blobPath) (languageToApiLanguage blobLanguage) (V.fromList (fmap tagToSymbol tags)) mempty tagsToFile Blob{..} tags = File (pack blobPath) (bridging # blobLanguage) (V.fromList (fmap tagToSymbol tags)) mempty
tagToSymbol :: Tag -> Symbol tagToSymbol :: Tag -> Symbol
tagToSymbol Tag{..} tagToSymbol Tag{..}
@ -74,6 +75,6 @@ parseSymbols blobs = ParseTreeSymbolResponse . V.fromList . toList <$> distribut
{ symbol = name { symbol = name
, kind = kind , kind = kind
, line = fromMaybe mempty line , line = fromMaybe mempty line
, span = spanToSpan span , span = converting #? span
, docs = fmap Docstring docs , docs = fmap Docstring docs
} }

View File

@ -1,8 +1,9 @@
{-# LANGUAGE GADTs, TypeOperators, DerivingStrategies #-} {-# LANGUAGE GADTs, TypeOperators, DerivingStrategies, LambdaCase #-}
module Semantic.Api.TOCSummaries (diffSummary, legacyDiffSummary, diffSummaryBuilder) where module Semantic.Api.TOCSummaries (diffSummary, legacyDiffSummary, diffSummaryBuilder) where
import Analysis.TOCSummary (Declaration, declarationAlgebra) import Analysis.TOCSummary (Declaration, declarationAlgebra)
import Control.Effect.Error import Control.Effect.Error
import Control.Lens
import Data.Aeson import Data.Aeson
import Data.Blob import Data.Blob
import Data.ByteString.Builder import Data.ByteString.Builder
@ -13,7 +14,7 @@ import qualified Data.Text as T
import qualified Data.Vector as V import qualified Data.Vector as V
import Rendering.TOC import Rendering.TOC
import Semantic.Api.Diffs import Semantic.Api.Diffs
import Semantic.Api.Helpers import Semantic.Api.Bridge
import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, BlobPair) import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, BlobPair)
import Semantic.Task as Task import Semantic.Task as Task
import Serializing.Format import Serializing.Format
@ -42,16 +43,22 @@ diffSummary blobs = DiffTreeTOCResponse . V.fromList <$> distributeFor blobs go
`catchError` \(SomeException e) -> `catchError` \(SomeException e) ->
pure $ TOCSummaryFile path lang mempty (V.fromList [TOCSummaryError (T.pack (show e)) Nothing]) pure $ TOCSummaryFile path lang mempty (V.fromList [TOCSummaryError (T.pack (show e)) Nothing])
where path = T.pack $ pathKeyForBlobPair blobPair where path = T.pack $ pathKeyForBlobPair blobPair
lang = languageToApiLanguage $ languageForBlobPair blobPair lang = bridging # languageForBlobPair blobPair
render :: (Foldable syntax, Functor syntax, Applicative m) => BlobPair -> Diff syntax (Maybe Declaration) (Maybe Declaration) -> m TOCSummaryFile render :: (Foldable syntax, Functor syntax, Applicative m) => BlobPair -> Diff syntax (Maybe Declaration) (Maybe Declaration) -> m TOCSummaryFile
render blobPair diff = pure $ foldr go (TOCSummaryFile path lang mempty mempty) (diffTOC diff) render blobPair diff = pure $ foldr go (TOCSummaryFile path lang mempty mempty) (diffTOC diff)
where where
path = T.pack $ pathKeyForBlobPair blobPair path = T.pack $ pathKeyForBlobPair blobPair
lang = languageToApiLanguage $ languageForBlobPair blobPair lang = bridging # languageForBlobPair blobPair
toChangeType = \case
"added" -> Added
"modified" -> Modified
"removed" -> Removed
_ -> None
go :: TOCSummary -> TOCSummaryFile -> TOCSummaryFile go :: TOCSummary -> TOCSummaryFile -> TOCSummaryFile
go TOCSummary{..} TOCSummaryFile{..} go TOCSummary{..} TOCSummaryFile{..}
= TOCSummaryFile path language (V.cons (TOCSummaryChange summaryCategoryName summaryTermName (spanToSpan summarySpan) (toChangeType summaryChangeType)) changes) errors = TOCSummaryFile path language (V.cons (TOCSummaryChange summaryCategoryName summaryTermName (converting #? summarySpan) (toChangeType summaryChangeType)) changes) errors
go ErrorSummary{..} TOCSummaryFile{..} go ErrorSummary{..} TOCSummaryFile{..}
= TOCSummaryFile path language changes (V.cons (TOCSummaryError errorText (spanToSpan errorSpan)) errors) = TOCSummaryFile path language changes (V.cons (TOCSummaryError errorText (converting #? errorSpan)) errors)

View File

@ -17,6 +17,7 @@ module Semantic.Api.Terms
import Analysis.ConstructorName (ConstructorName) import Analysis.ConstructorName (ConstructorName)
import Control.Effect import Control.Effect
import Control.Effect.Error import Control.Effect.Error
import Control.Lens
import Control.Monad import Control.Monad
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Data.Abstract.Declarations import Data.Abstract.Declarations
@ -36,7 +37,7 @@ import Prologue
import Rendering.Graph import Rendering.Graph
import Rendering.JSON hiding (JSON) import Rendering.JSON hiding (JSON)
import qualified Rendering.JSON import qualified Rendering.JSON
import Semantic.Api.Helpers import Semantic.Api.Bridge
import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, Language (..)) import Semantic.Api.V1.CodeAnalysisPB hiding (Blob, Language (..))
import Semantic.Task import Semantic.Task
import Serializing.Format hiding (JSON) import Serializing.Format hiding (JSON)
@ -52,7 +53,7 @@ termGraph blobs = ParseTreeGraphResponse . V.fromList . toList <$> distributeFor
pure (ParseTreeFileGraph path lang mempty mempty (V.fromList [ParseError (T.pack (show e))])) pure (ParseTreeFileGraph path lang mempty mempty (V.fromList [ParseError (T.pack (show e))]))
where where
path = T.pack $ blobPath blob path = T.pack $ blobPath blob
lang = languageToApiLanguage $ blobLanguage blob lang = bridging # blobLanguage blob
render :: (Foldable syntax, Functor syntax, ConstructorName syntax) => Term syntax Location -> ParseTreeFileGraph render :: (Foldable syntax, Functor syntax, ConstructorName syntax) => Term syntax Location -> ParseTreeFileGraph
render t = let graph = renderTreeGraph t render t = let graph = renderTreeGraph t
@ -101,7 +102,7 @@ quietTerm blob = showTiming blob <$> time' ( (doParse blob >>= withSomeTerm (fma
in stringUtf8 (status <> "\t" <> show blobLanguage <> "\t" <> blobPath <> "\t" <> show duration <> " ms\n") in stringUtf8 (status <> "\t" <> show blobLanguage <> "\t" <> blobPath <> "\t" <> show duration <> " ms\n")
type ParseEffects sig m = (Member (Error SomeException) sig, Member Task sig, Carrier sig m, Monad m) type ParseEffects sig m = (Member (Error SomeException) sig, Member Task sig, Carrier sig m)
type TermConstraints = type TermConstraints =
'[ Taggable '[ Taggable

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ExistentialQuantification, TypeOperators, UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification, GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances #-}
module Semantic.Distribute module Semantic.Distribute
( distribute ( distribute
, distributeFor , distributeFor
@ -18,19 +18,19 @@ import Prologue
-- | Distribute a 'Traversable' container of tasks over the available cores (i.e. execute them concurrently), collecting their results. -- | Distribute a 'Traversable' container of tasks over the available cores (i.e. execute them concurrently), collecting their results.
-- --
-- This is a concurrent analogue of 'sequenceA'. -- This is a concurrent analogue of 'sequenceA'.
distribute :: (Member Distribute sig, Traversable t, Carrier sig m, Applicative m) => t (m output) -> m (t output) distribute :: (Member Distribute sig, Traversable t, Carrier sig m) => t (m output) -> m (t output)
distribute = fmap (withStrategy (parTraversable rseq)) <$> traverse (send . flip Distribute ret) distribute = fmap (withStrategy (parTraversable rseq)) <$> traverse (send . flip Distribute pure)
-- | Distribute the application of a function to each element of a 'Traversable' container of inputs over the available cores (i.e. perform the function concurrently for each element), collecting the results. -- | Distribute the application of a function to each element of a 'Traversable' container of inputs over the available cores (i.e. perform the function concurrently for each element), collecting the results.
-- --
-- This is a concurrent analogue of 'for' or 'traverse' (with the arguments flipped). -- This is a concurrent analogue of 'for' or 'traverse' (with the arguments flipped).
distributeFor :: (Member Distribute sig, Traversable t, Carrier sig m, Applicative m) => t a -> (a -> m output) -> m (t output) distributeFor :: (Member Distribute sig, Traversable t, Carrier sig m) => t a -> (a -> m output) -> m (t output)
distributeFor inputs toTask = distribute (fmap toTask inputs) distributeFor inputs toTask = distribute (fmap toTask inputs)
-- | Distribute the application of a function to each element of a 'Traversable' container of inputs over the available cores (i.e. perform the function concurrently for each element), combining the results 'Monoid'ally into a final value. -- | Distribute the application of a function to each element of a 'Traversable' container of inputs over the available cores (i.e. perform the function concurrently for each element), combining the results 'Monoid'ally into a final value.
-- --
-- This is a concurrent analogue of 'foldMap'. -- This is a concurrent analogue of 'foldMap'.
distributeFoldMap :: (Member Distribute sig, Monoid output, Traversable t, Carrier sig m, Applicative m) => (a -> m output) -> t a -> m output distributeFoldMap :: (Member Distribute sig, Monoid output, Traversable t, Carrier sig m) => (a -> m output) -> t a -> m output
distributeFoldMap toTask inputs = fmap fold (distribute (fmap toTask inputs)) distributeFoldMap toTask inputs = fmap fold (distribute (fmap toTask inputs))
@ -48,13 +48,12 @@ instance Effect Distribute where
-- | Evaluate a 'Distribute' effect concurrently. -- | Evaluate a 'Distribute' effect concurrently.
runDistribute :: Eff (DistributeC (Eff (LiftC IO))) a -> Eff (LiftC IO) a runDistribute :: DistributeC (LiftC IO) a -> LiftC IO a
runDistribute = runDistributeC . interpret runDistribute = runDistributeC
newtype DistributeC m a = DistributeC { runDistributeC :: m a } newtype DistributeC m a = DistributeC { runDistributeC :: m a }
deriving (Functor, Applicative, Monad, MonadIO)
instance Carrier (Distribute :+: Lift IO) (DistributeC (Eff (LiftC IO))) where instance Carrier (Distribute :+: Lift IO) (DistributeC (LiftC IO)) where
ret = DistributeC . ret eff (L (Distribute task k)) = liftIO (Async.runConcurrently (Async.Concurrently (runM . runDistributeC $ task))) >>= k
eff = DistributeC . handleSum eff (R other) = DistributeC (eff (handleCoercible other))
(eff . handleCoercible)
(\ (Distribute task k) -> liftIO (Async.runConcurrently (Async.Concurrently (runM (runDistributeC task)))) >>= runDistributeC . k)

View File

@ -82,7 +82,7 @@ runGraph :: ( Member Distribute sig
=> GraphType => GraphType
-> Bool -> Bool
-> Project -> Project
-> Eff m (Graph ControlFlowVertex) -> m (Graph ControlFlowVertex)
runGraph ImportGraph _ project runGraph ImportGraph _ project
| SomeAnalysisParser parser (lang' :: Proxy lang) <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do | SomeAnalysisParser parser (lang' :: Proxy lang) <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do
let parse = if projectLanguage project == Language.Python then parsePythonPackage parser else fmap (fmap snd) . parsePackage parser let parse = if projectLanguage project == Language.Python then parsePythonPackage parser else fmap (fmap snd) . parsePackage parser
@ -112,7 +112,7 @@ runCallGraph :: ( VertexDeclarationWithStrategy (VertexDeclarationStrategy synta
-> Bool -> Bool
-> [Module term] -> [Module term]
-> Package term -> Package term
-> Eff m (Graph ControlFlowVertex) -> m (Graph ControlFlowVertex)
runCallGraph lang includePackages modules package runCallGraph lang includePackages modules package
= fmap (simplify . fst) = fmap (simplify . fst)
. runEvaluator . runEvaluator
@ -140,8 +140,7 @@ runCallGraph lang includePackages modules package
perModule = (if includePackages then graphingPackages else id) . convergingModules . graphingModules $ runDomainEffects perTerm perModule = (if includePackages then graphingPackages else id) . convergingModules . graphingModules $ runDomainEffects perTerm
runModuleTable :: Carrier sig m runModuleTable :: Evaluator term address value (ReaderC (ModuleTable (Module (ModuleResult address value))) m) a
=> Evaluator term address value (ReaderC (ModuleTable (Module (ModuleResult address value))) (Eff m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
runModuleTable = raiseHandler $ runReader lowerBound runModuleTable = raiseHandler $ runReader lowerBound
@ -159,7 +158,7 @@ runImportGraphToModuleInfos :: ( Declarations term
) )
=> Proxy lang => Proxy lang
-> Package term -> Package term
-> Eff m (Graph ControlFlowVertex) -> m (Graph ControlFlowVertex)
runImportGraphToModuleInfos lang (package :: Package term) = runImportGraph lang package allModuleInfos runImportGraphToModuleInfos lang (package :: Package term) = runImportGraph lang package allModuleInfos
where allModuleInfos info = vertex (maybe (unknownModuleVertex info) (moduleVertex . moduleInfo) (ModuleTable.lookup (modulePath info) (packageModules package))) where allModuleInfos info = vertex (maybe (unknownModuleVertex info) (moduleVertex . moduleInfo) (ModuleTable.lookup (modulePath info) (packageModules package)))
@ -177,7 +176,7 @@ runImportGraphToModules :: ( Declarations term
) )
=> Proxy lang => Proxy lang
-> Package term -> Package term
-> Eff m (Graph (Module term)) -> m (Graph (Module term))
runImportGraphToModules lang (package :: Package term) = runImportGraph lang package resolveOrLowerBound runImportGraphToModules lang (package :: Package term) = runImportGraph lang package resolveOrLowerBound
where resolveOrLowerBound info = maybe lowerBound vertex (ModuleTable.lookup (modulePath info) (packageModules package)) where resolveOrLowerBound info = maybe lowerBound vertex (ModuleTable.lookup (modulePath info) (packageModules package))
@ -196,7 +195,7 @@ runImportGraph :: ( AccessControls term
=> Proxy lang => Proxy lang
-> Package term -> Package term
-> (ModuleInfo -> Graph vertex) -> (ModuleInfo -> Graph vertex)
-> Eff m (Graph vertex) -> m (Graph vertex)
runImportGraph lang (package :: Package term) f runImportGraph lang (package :: Package term) f
= fmap (fst >=> f) = fmap (fst >=> f)
. runEvaluator @_ @_ @(Value _ (Hole (Maybe Name) Precise)) . runEvaluator @_ @_ @(Value _ (Hole (Maybe Name) Precise))
@ -220,18 +219,17 @@ runImportGraph lang (package :: Package term) f
. runAllocator . runAllocator
$ evaluate lang (graphingModuleInfo (runDomainEffects (evalTerm id))) (snd <$> ModuleTable.toPairs (packageModules package)) $ evaluate lang (graphingModuleInfo (runDomainEffects (evalTerm id))) (snd <$> ModuleTable.toPairs (packageModules package))
runHeap :: (Carrier sig m, Effect sig) runHeap :: Evaluator term address value (StateC (Heap address address value) m) a
=> Evaluator term address value (StateC (Heap address address value) (Eff m)) a
-> Evaluator term address value m (Heap address address value, a) -> Evaluator term address value m (Heap address address value, a)
runHeap = raiseHandler (runState lowerBound) runHeap = raiseHandler (runState lowerBound)
runScopeGraph :: (Carrier sig m, Effect sig, Ord address) runScopeGraph :: Ord address
=> Evaluator term address value (StateC (ScopeGraph address) (Eff m)) a => Evaluator term address value (StateC (ScopeGraph address) m) a
-> Evaluator term address value m (ScopeGraph address, a) -> Evaluator term address value m (ScopeGraph address, a)
runScopeGraph = raiseHandler (runState lowerBound) runScopeGraph = raiseHandler (runState lowerBound)
-- | Parse a list of files into a 'Package'. -- | Parse a list of files into a 'Package'.
parsePackage :: (Member Distribute sig, Member (Error SomeException) sig, Member Resolution sig, Member Task sig, Member Trace sig, Carrier sig m, Monad m) parsePackage :: (Member Distribute sig, Member (Error SomeException) sig, Member Resolution sig, Member Task sig, Member Trace sig, Carrier sig m)
=> Parser term -- ^ A parser. => Parser term -- ^ A parser.
-> Project -- ^ Project to parse into a package. -> Project -- ^ Project to parse into a package.
-> m (Package (Blob, term)) -> m (Package (Blob, term))
@ -245,7 +243,7 @@ parsePackage parser project = do
n = Data.Abstract.Evaluatable.name (projectName project) -- TODO: Confirm this is the right `name`. n = Data.Abstract.Evaluatable.name (projectName project) -- TODO: Confirm this is the right `name`.
-- | Parse all files in a project into 'Module's. -- | Parse all files in a project into 'Module's.
parseModules :: (Member Distribute sig, Member (Error SomeException) sig, Member Task sig, Carrier sig m, Monad m) => Parser term -> Project -> m [Module (Blob, term)] parseModules :: (Member Distribute sig, Member (Error SomeException) sig, Member Task sig, Carrier sig m) => Parser term -> Project -> m [Module (Blob, term)]
parseModules parser p@Project{..} = distributeFor (projectFiles p) (parseModule p parser) parseModules parser p@Project{..} = distributeFor (projectFiles p) (parseModule p parser)
@ -267,7 +265,7 @@ parsePythonPackage :: forall syntax sig m term.
) )
=> Parser term -- ^ A parser. => Parser term -- ^ A parser.
-> Project -- ^ Project to parse into a package. -> Project -- ^ Project to parse into a package.
-> Eff m (Package term) -> m (Package term)
parsePythonPackage parser project = do parsePythonPackage parser project = do
let runAnalysis = runEvaluator @_ @_ @(Value term (Hole (Maybe Name) Precise)) let runAnalysis = runEvaluator @_ @_ @(Value term (Hole (Maybe Name) Precise))
. raiseHandler (runState PythonPackage.Unknown) . raiseHandler (runState PythonPackage.Unknown)
@ -321,7 +319,7 @@ parsePythonPackage parser project = do
resMap <- Task.resolutionMap p resMap <- Task.resolutionMap p
pure (Package.fromModules (Data.Abstract.Evaluatable.name $ projectName p) modules resMap) -- TODO: Confirm this is the right `name`. pure (Package.fromModules (Data.Abstract.Evaluatable.name $ projectName p) modules resMap) -- TODO: Confirm this is the right `name`.
parseModule :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m, Monad m) parseModule :: (Member (Error SomeException) sig, Member Task sig, Carrier sig m)
=> Project => Project
-> Parser term -> Parser term
-> File -> File
@ -347,19 +345,20 @@ withTermSpans recur term = let
resumingResolutionError :: ( Member Trace sig resumingResolutionError :: ( Member Trace sig
, Carrier sig m , Carrier sig m
) )
=> Evaluator term address value (ResumableWithC (BaseError ResolutionError) (Eff => Evaluator term address value (ResumableWithC (BaseError ResolutionError) m) a
m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingResolutionError = runResolutionErrorWith (\ baseError -> traceError "ResolutionError" baseError *> case baseErrorException baseError of resumingResolutionError = runResolutionErrorWith $ \ baseError -> do
NotFoundError nameToResolve _ _ -> pure nameToResolve traceError "ResolutionError" baseError
GoImportError pathToResolve -> pure [pathToResolve]) case baseErrorException baseError of
NotFoundError nameToResolve _ _ -> pure nameToResolve
GoImportError pathToResolve -> pure [pathToResolve]
resumingLoadError :: ( Carrier sig m resumingLoadError :: ( Carrier sig m
, Member Trace sig , Member Trace sig
, AbstractHole value , AbstractHole value
, AbstractHole address , AbstractHole address
) )
=> Evaluator term address value (ResumableWithC (BaseError (LoadError address value)) (Eff m)) a => Evaluator term address value (ResumableWithC (BaseError (LoadError address value)) m) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingLoadError = runLoadErrorWith (\ baseError -> traceError "LoadError" baseError *> case baseErrorException baseError of resumingLoadError = runLoadErrorWith (\ baseError -> traceError "LoadError" baseError *> case baseErrorException baseError of
ModuleNotFoundError _ -> pure ((hole, hole), hole)) ModuleNotFoundError _ -> pure ((hole, hole), hole))
@ -372,8 +371,7 @@ resumingEvalError :: ( Carrier sig m
, AbstractHole address , AbstractHole address
, AbstractHole value , AbstractHole value
) )
=> Evaluator term address value (ResumableWithC (BaseError (EvalError term address value)) (Eff => Evaluator term address value (ResumableWithC (BaseError (EvalError term address value)) m) a
m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingEvalError = runEvalErrorWith (\ baseError -> traceError "EvalError" baseError *> case baseErrorException baseError of resumingEvalError = runEvalErrorWith (\ baseError -> traceError "EvalError" baseError *> case baseErrorException baseError of
AccessControlError{} -> pure hole AccessControlError{} -> pure hole
@ -393,8 +391,7 @@ resumingUnspecialized :: ( AbstractHole address
, Carrier sig m , Carrier sig m
, Member Trace sig , Member Trace sig
) )
=> Evaluator term address value (ResumableWithC (BaseError (UnspecializedError address value)) (Eff => Evaluator term address value (ResumableWithC (BaseError (UnspecializedError address value)) m) a
m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingUnspecialized = runUnspecializedWith (\ baseError -> traceError "UnspecializedError" baseError *> case baseErrorException baseError of resumingUnspecialized = runUnspecializedWith (\ baseError -> traceError "UnspecializedError" baseError *> case baseErrorException baseError of
UnspecializedError _ -> pure hole UnspecializedError _ -> pure hole
@ -405,20 +402,20 @@ resumingAddressError :: ( AbstractHole value
, Member Trace sig , Member Trace sig
, Show address , Show address
) )
=> Evaluator term address value (ResumableWithC (BaseError (AddressError address value)) (Eff => Evaluator term address value (ResumableWithC (BaseError (AddressError address value)) m) a
m)) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingAddressError = runAddressErrorWith $ \ baseError -> traceError "AddressError" baseError *> case baseErrorException baseError of resumingAddressError = runAddressErrorWith $ \ baseError -> do
UnallocatedSlot _ -> pure lowerBound traceError "AddressError" baseError
UninitializedSlot _ -> pure hole case baseErrorException baseError of
UnallocatedSlot _ -> pure lowerBound
UninitializedSlot _ -> pure hole
resumingValueError :: ( Carrier sig m resumingValueError :: ( Carrier sig m
, Member Trace sig , Member Trace sig
, Show address , Show address
, Show term , Show term
) )
=> Evaluator term address (Value term address) (ResumableWithC (BaseError (ValueError term address)) (Eff => Evaluator term address (Value term address) (ResumableWithC (BaseError (ValueError term address)) m) a
m)) a
-> Evaluator term address (Value term address) m a -> Evaluator term address (Value term address) m a
resumingValueError = runValueErrorWith (\ baseError -> traceError "ValueError" baseError *> case baseErrorException baseError of resumingValueError = runValueErrorWith (\ baseError -> traceError "ValueError" baseError *> case baseErrorException baseError of
CallError{} -> pure hole CallError{} -> pure hole
@ -440,7 +437,7 @@ resumingHeapError :: ( Carrier sig m
, Member Trace sig , Member Trace sig
, Show address , Show address
) )
=> Evaluator term address value (ResumableWithC (BaseError (HeapError address)) (Eff m)) a => Evaluator term address value (ResumableWithC (BaseError (HeapError address)) m) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingHeapError = runHeapErrorWith (\ baseError -> traceError "ScopeError" baseError *> case baseErrorException baseError of resumingHeapError = runHeapErrorWith (\ baseError -> traceError "ScopeError" baseError *> case baseErrorException baseError of
CurrentFrameError -> pure hole CurrentFrameError -> pure hole
@ -458,7 +455,7 @@ resumingScopeError :: ( Carrier sig m
, AbstractHole (Info address) , AbstractHole (Info address)
, AbstractHole address , AbstractHole address
) )
=> Evaluator term address value (ResumableWithC (BaseError (ScopeError address)) (Eff m)) a => Evaluator term address value (ResumableWithC (BaseError (ScopeError address)) m) a
-> Evaluator term address value m a -> Evaluator term address value m a
resumingScopeError = runScopeErrorWith (\ baseError -> traceError "ScopeError" baseError *> case baseErrorException baseError of resumingScopeError = runScopeErrorWith (\ baseError -> traceError "ScopeError" baseError *> case baseErrorException baseError of
ScopeError _ _ -> pure hole ScopeError _ _ -> pure hole
@ -470,13 +467,13 @@ resumingScopeError = runScopeErrorWith (\ baseError -> traceError "ScopeError" b
DeclarationByNameError _ -> pure hole) DeclarationByNameError _ -> pure hole)
resumingTypeError :: ( Carrier sig m resumingTypeError :: ( Carrier sig m
, Member NonDet sig
, Member Trace sig , Member Trace sig
, Effect sig , Effect sig
, Alternative m
) )
=> Evaluator term address Type (ResumableWithC (BaseError TypeError) (Eff => Evaluator term address Type (ResumableWithC (BaseError TypeError)
(StateC TypeMap (Eff (StateC TypeMap
m)))) a m)) a
-> Evaluator term address Type m a -> Evaluator term address Type m a
resumingTypeError = runTypesWith (\ baseError -> traceError "TypeError" baseError *> case baseErrorException baseError of resumingTypeError = runTypesWith (\ baseError -> traceError "TypeError" baseError *> case baseErrorException baseError of
UnificationError l r -> pure l <|> pure r UnificationError l r -> pure l <|> pure r

View File

@ -1,4 +1,4 @@
{-# LANGUAGE GADTs, LambdaCase, TypeOperators, UndecidableInstances #-} {-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-missing-signatures #-} {-# OPTIONS_GHC -Wno-missing-signatures #-}
module Semantic.REPL module Semantic.REPL
( rubyREPL ( rubyREPL
@ -100,20 +100,23 @@ repl proxy parser paths =
-- TODO: drive the flow from within the REPL instead of from without -- TODO: drive the flow from within the REPL instead of from without
runTelemetryIgnoringStat :: (Carrier sig m, MonadIO m) => LogOptions -> Eff (TelemetryIgnoringStatC m) a -> m a runTelemetryIgnoringStat :: LogOptions -> TelemetryIgnoringStatC m a -> m a
runTelemetryIgnoringStat logOptions = flip runTelemetryIgnoringStatC logOptions . interpret runTelemetryIgnoringStat logOptions = runReader logOptions . runTelemetryIgnoringStatC
newtype TelemetryIgnoringStatC m a = TelemetryIgnoringStatC { runTelemetryIgnoringStatC :: LogOptions -> m a } newtype TelemetryIgnoringStatC m a = TelemetryIgnoringStatC { runTelemetryIgnoringStatC :: ReaderC LogOptions m a }
deriving (Applicative, Functor, Monad, MonadIO)
instance (Carrier sig m, MonadIO m) => Carrier (Telemetry :+: sig) (TelemetryIgnoringStatC m) where instance (Carrier sig m, MonadIO m) => Carrier (Telemetry :+: sig) (TelemetryIgnoringStatC m) where
ret = TelemetryIgnoringStatC . const . ret eff (R other) = TelemetryIgnoringStatC . eff . R . handleCoercible $ other
eff op = TelemetryIgnoringStatC (\ logOptions -> handleSum (eff . handleReader logOptions runTelemetryIgnoringStatC) (\case eff (L op) = do
WriteStat _ k -> runTelemetryIgnoringStatC k logOptions logOptions <- TelemetryIgnoringStatC ask
WriteLog level message pairs k -> do case op of
time <- liftIO Time.getCurrentTime WriteStat _ k -> k
zonedTime <- liftIO (LocalTime.utcToLocalZonedTime time) WriteLog level message pairs k -> do
writeLogMessage logOptions (Message level message pairs zonedTime) time <- liftIO Time.getCurrentTime
runTelemetryIgnoringStatC k logOptions) op) zonedTime <- liftIO (LocalTime.utcToLocalZonedTime time)
writeLogMessage logOptions (Message level message pairs zonedTime)
k
step :: ( Member (Error SomeException) sig step :: ( Member (Error SomeException) sig
, Member REPL sig , Member REPL sig

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ConstraintKinds, GADTs, KindSignatures, LambdaCase, ScopedTypeVariables, TypeOperators, UndecidableInstances #-} {-# LANGUAGE ConstraintKinds, GADTs, GeneralizedNewtypeDeriving, KindSignatures, ScopedTypeVariables, TypeOperators, UndecidableInstances #-}
module Semantic.Resolution module Semantic.Resolution
( Resolution (..) ( Resolution (..)
, nodeJSResolutionMap , nodeJSResolutionMap
@ -24,7 +24,7 @@ import Semantic.Task.Files
import System.FilePath.Posix import System.FilePath.Posix
nodeJSResolutionMap :: (Member Files sig, Carrier sig m, Monad m) => FilePath -> Text -> [FilePath] -> m (Map FilePath FilePath) nodeJSResolutionMap :: (Member Files sig, Carrier sig m) => FilePath -> Text -> [FilePath] -> m (Map FilePath FilePath)
nodeJSResolutionMap rootDir prop excludeDirs = do nodeJSResolutionMap rootDir prop excludeDirs = do
files <- findFiles rootDir [".json"] excludeDirs files <- findFiles rootDir [".json"] excludeDirs
let packageFiles = file <$> filter ((==) "package.json" . takeFileName) files let packageFiles = file <$> filter ((==) "package.json" . takeFileName) files
@ -41,9 +41,9 @@ nodeJSResolutionMap rootDir prop excludeDirs = do
resolutionMap :: (Member Resolution sig, Carrier sig m) => Project -> m (Map FilePath FilePath) resolutionMap :: (Member Resolution sig, Carrier sig m) => Project -> m (Map FilePath FilePath)
resolutionMap Project{..} = case projectLanguage of resolutionMap Project{..} = case projectLanguage of
TypeScript -> send (NodeJSResolution projectRootDir "types" projectExcludeDirs ret) TypeScript -> send (NodeJSResolution projectRootDir "types" projectExcludeDirs pure)
JavaScript -> send (NodeJSResolution projectRootDir "main" projectExcludeDirs ret) JavaScript -> send (NodeJSResolution projectRootDir "main" projectExcludeDirs pure)
_ -> send (NoResolution ret) _ -> send (NoResolution pure)
data Resolution (m :: * -> *) k data Resolution (m :: * -> *) k
= NodeJSResolution FilePath Text [FilePath] (Map FilePath FilePath -> k) = NodeJSResolution FilePath Text [FilePath] (Map FilePath FilePath -> k)
@ -57,13 +57,14 @@ instance Effect Resolution where
handle state handler (NodeJSResolution path key paths k) = NodeJSResolution path key paths (handler . (<$ state) . k) handle state handler (NodeJSResolution path key paths k) = NodeJSResolution path key paths (handler . (<$ state) . k)
handle state handler (NoResolution k) = NoResolution (handler . (<$ state) . k) handle state handler (NoResolution k) = NoResolution (handler . (<$ state) . k)
runResolution :: (Member Files sig, Carrier sig m, Monad m) => Eff (ResolutionC m) a -> m a runResolution :: ResolutionC m a -> m a
runResolution = runResolutionC . interpret runResolution = runResolutionC
newtype ResolutionC m a = ResolutionC { runResolutionC :: m a } newtype ResolutionC m a = ResolutionC { runResolutionC :: m a }
deriving (Applicative, Functor, Monad, MonadIO)
instance (Member Files sig, Carrier sig m, Monad m) => Carrier (Resolution :+: sig) (ResolutionC m) where instance (Member Files sig, Carrier sig m) => Carrier (Resolution :+: sig) (ResolutionC m) where
ret = ResolutionC . ret eff (R other) = ResolutionC . eff . handleCoercible $ other
eff = ResolutionC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
NodeJSResolution dir prop excludeDirs k -> nodeJSResolutionMap dir prop excludeDirs >>= runResolutionC . k NodeJSResolution dir prop excludeDirs k -> nodeJSResolutionMap dir prop excludeDirs >>= k
NoResolution k -> runResolutionC (k Map.empty)) NoResolution k -> k Map.empty

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ConstraintKinds, ExistentialQuantification, GADTs, KindSignatures, LambdaCase, ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-} {-# LANGUAGE ConstraintKinds, ExistentialQuantification, GADTs, GeneralizedNewtypeDeriving, KindSignatures, ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
module Semantic.Task module Semantic.Task
( Task ( Task
, TaskEff , TaskEff
@ -47,7 +47,6 @@ module Semantic.Task
, ParserCancelled(..) , ParserCancelled(..)
-- * Re-exports -- * Re-exports
, Distribute , Distribute
, Eff
, Error , Error
, Lift , Lift
, throwError , throwError
@ -95,17 +94,17 @@ import Serializing.Format hiding (Options)
-- | A high-level task producing some result, e.g. parsing, diffing, rendering. 'Task's can also specify explicit concurrency via 'distribute', 'distributeFor', and 'distributeFoldMap' -- | A high-level task producing some result, e.g. parsing, diffing, rendering. 'Task's can also specify explicit concurrency via 'distribute', 'distributeFor', and 'distributeFoldMap'
type TaskEff type TaskEff
= Eff (TaskC = TaskC
( Eff (ResolutionC ( ResolutionC
( Eff (Files.FilesC ( Files.FilesC
( Eff (ReaderC TaskSession ( ReaderC TaskSession
( Eff (TraceInTelemetryC ( TraceInTelemetryC
( Eff (TelemetryC ( TelemetryC
( Eff (ErrorC SomeException ( ErrorC SomeException
( Eff (TimeoutC ( TimeoutC
( Eff (ResourceC ( ResourceC
( Eff (DistributeC ( DistributeC
( Eff (LiftC IO))))))))))))))))))))) ( LiftC IO))))))))))
-- | A function to render terms or diffs. -- | A function to render terms or diffs.
type Renderer i o = i -> o type Renderer i o = i -> o
@ -115,40 +114,40 @@ parse :: (Member Task sig, Carrier sig m)
=> Parser term => Parser term
-> Blob -> Blob
-> m term -> m term
parse parser blob = send (Parse parser blob ret) parse parser blob = send (Parse parser blob pure)
-- | A task running some 'Analysis.Evaluator' to completion. -- | A task running some 'Analysis.Evaluator' to completion.
analyze :: (Member Task sig, Carrier sig m) analyze :: (Member Task sig, Carrier sig m)
=> (Analysis.Evaluator term address value m a -> result) => (Analysis.Evaluator term address value m a -> result)
-> Analysis.Evaluator term address value m a -> Analysis.Evaluator term address value m a
-> m result -> m result
analyze interpret analysis = send (Analyze interpret analysis ret) analyze interpret analysis = send (Analyze interpret analysis pure)
-- | A task which decorates a 'Term' with values computed using the supplied 'RAlgebra' function. -- | A task which decorates a 'Term' with values computed using the supplied 'RAlgebra' function.
decorate :: (Functor f, Member Task sig, Carrier sig m) decorate :: (Functor f, Member Task sig, Carrier sig m)
=> RAlgebra (TermF f Location) (Term f Location) field => RAlgebra (TermF f Location) (Term f Location) field
-> Term f Location -> Term f Location
-> m (Term f field) -> m (Term f field)
decorate algebra term = send (Decorate algebra term ret) decorate algebra term = send (Decorate algebra term pure)
-- | A task which diffs a pair of terms using the supplied 'Differ' function. -- | A task which diffs a pair of terms using the supplied 'Differ' function.
diff :: (Diffable syntax, Eq1 syntax, Hashable1 syntax, Traversable syntax, Member Task sig, Carrier sig m) diff :: (Diffable syntax, Eq1 syntax, Hashable1 syntax, Traversable syntax, Member Task sig, Carrier sig m)
=> These (Term syntax ann) (Term syntax ann) => These (Term syntax ann) (Term syntax ann)
-> m (Diff syntax ann ann) -> m (Diff syntax ann ann)
diff terms = send (Semantic.Task.Diff terms ret) diff terms = send (Semantic.Task.Diff terms pure)
-- | A task which renders some input using the supplied 'Renderer' function. -- | A task which renders some input using the supplied 'Renderer' function.
render :: (Member Task sig, Carrier sig m) render :: (Member Task sig, Carrier sig m)
=> Renderer input output => Renderer input output
-> input -> input
-> m output -> m output
render renderer input = send (Render renderer input ret) render renderer input = send (Render renderer input pure)
serialize :: (Member Task sig, Carrier sig m) serialize :: (Member Task sig, Carrier sig m)
=> Format input => Format input
-> input -> input
-> m Builder -> m Builder
serialize format input = send (Serialize format input ret) serialize format input = send (Serialize format input pure)
data TaskSession data TaskSession
= TaskSession = TaskSession
@ -191,18 +190,16 @@ withOptions options with = do
config <- defaultConfig options config <- defaultConfig options
withTelemetry config (\ (TelemetryQueues logger statter _) -> with config logger statter) withTelemetry config (\ (TelemetryQueues logger statter _) -> with config logger statter)
runTraceInTelemetry :: (Member Telemetry sig, Carrier sig m, Monad m) runTraceInTelemetry :: TraceInTelemetryC m a
=> Eff (TraceInTelemetryC m) a
-> m a -> m a
runTraceInTelemetry = runTraceInTelemetryC . interpret runTraceInTelemetry = runTraceInTelemetryC
newtype TraceInTelemetryC m a = TraceInTelemetryC { runTraceInTelemetryC :: m a } newtype TraceInTelemetryC m a = TraceInTelemetryC { runTraceInTelemetryC :: m a }
deriving (Applicative, Functor, Monad, MonadIO)
instance (Member Telemetry sig, Carrier sig m, Monad m) => Carrier (Trace :+: sig) (TraceInTelemetryC m) where instance (Member Telemetry sig, Carrier sig m) => Carrier (Trace :+: sig) (TraceInTelemetryC m) where
ret = TraceInTelemetryC . ret eff (R other) = TraceInTelemetryC . eff . handleCoercible $ other
eff = TraceInTelemetryC . handleSum eff (L (Trace str k)) = writeLog Debug str [] >> k
(eff . handleCoercible)
(\ (Trace str k) -> writeLog Debug str [] >> runTraceInTelemetryC k)
-- | An effect describing high-level tasks to be performed. -- | An effect describing high-level tasks to be performed.
@ -228,33 +225,23 @@ instance Effect Task where
handle state handler (Serialize format input k) = Serialize format input (handler . (<$ state) . k) handle state handler (Serialize format input k) = Serialize format input (handler . (<$ state) . k)
-- | Run a 'Task' effect by performing the actions in 'IO'. -- | Run a 'Task' effect by performing the actions in 'IO'.
runTaskF :: ( Member (Error SomeException) sig runTaskF :: TaskC m a -> m a
, Member (Lift IO) sig runTaskF = runTaskC
, Member (Reader TaskSession) sig
, Member Resource sig
, Member Telemetry sig
, Member Timeout sig
, Member Trace sig
, Carrier sig m
, MonadIO m
)
=> Eff (TaskC m) a
-> m a
runTaskF = runTaskC . interpret
newtype TaskC m a = TaskC { runTaskC :: m a } newtype TaskC m a = TaskC { runTaskC :: m a }
deriving (Applicative, Functor, Monad, MonadIO)
instance (Member (Error SomeException) sig, Member (Lift IO) sig, Member (Reader TaskSession) sig, Member Resource sig, Member Telemetry sig, Member Timeout sig, Member Trace sig, Carrier sig m, MonadIO m) => Carrier (Task :+: sig) (TaskC m) where instance (Member (Error SomeException) sig, Member (Lift IO) sig, Member (Reader TaskSession) sig, Member Resource sig, Member Telemetry sig, Member Timeout sig, Member Trace sig, Carrier sig m, MonadIO m) => Carrier (Task :+: sig) (TaskC m) where
ret = TaskC . ret eff (R other) = TaskC . eff . handleCoercible $ other
eff = TaskC . handleSum (eff . handleCoercible) (\case eff (L op) = case op of
Parse parser blob k -> runParser blob parser >>= runTaskC . k Parse parser blob k -> runParser blob parser >>= k
Analyze interpret analysis k -> runTaskC (k (interpret analysis)) Analyze interpret analysis k -> k . interpret $ analysis
Decorate algebra term k -> runTaskC (k (decoratorWithAlgebra algebra term)) Decorate algebra term k -> k (decoratorWithAlgebra algebra term)
Semantic.Task.Diff terms k -> runTaskC (k (diffTermPair terms)) Semantic.Task.Diff terms k -> k (diffTermPair terms)
Render renderer input k -> runTaskC (k (renderer input)) Render renderer input k -> k (renderer input)
Serialize format input k -> do Serialize format input k -> do
formatStyle <- asks (bool Plain Colourful . configIsTerminal . config) formatStyle <- asks (bool Plain Colourful . configIsTerminal . config)
runTaskC (k (runSerialize formatStyle format input))) k (runSerialize formatStyle format input)
-- | Log an 'Error.Error' at the specified 'Level'. -- | Log an 'Error.Error' at the specified 'Level'.

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ExistentialQuantification, GADTs, LambdaCase, KindSignatures, TypeOperators, UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification, GADTs, GeneralizedNewtypeDeriving, KindSignatures, TypeOperators, UndecidableInstances #-}
module Semantic.Task.Files module Semantic.Task.Files
( Files ( Files
@ -59,46 +59,47 @@ instance Effect Files where
handle state handler (Write destination builder k) = Write destination builder (handler (k <$ state)) handle state handler (Write destination builder k) = Write destination builder (handler (k <$ state))
-- | Run a 'Files' effect in 'IO'. -- | Run a 'Files' effect in 'IO'.
runFiles :: (Member (Error SomeException) sig, MonadIO m, Carrier sig m) => Eff (FilesC m) a -> m a runFiles :: FilesC m a -> m a
runFiles = runFilesC . interpret runFiles = runFilesC
newtype FilesC m a = FilesC { runFilesC :: m a } newtype FilesC m a = FilesC { runFilesC :: m a }
deriving (Functor, Applicative, Monad, MonadIO)
instance (Member (Error SomeException) sig, MonadIO m, Carrier sig m) => Carrier (Files :+: sig) (FilesC m) where instance (Member (Error SomeException) sig, MonadIO m, Carrier sig m) => Carrier (Files :+: sig) (FilesC m) where
ret = FilesC . ret eff (L op) = case op of
eff = FilesC . handleSum (eff . handleCoercible) (\case Read (FromPath path) k -> (readBlobFromFile' path `catchIO` (throwError . toException @SomeException)) >>= k
Read (FromPath path) k -> (readBlobFromFile' path `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k Read (FromHandle handle) k -> (readBlobsFromHandle handle `catchIO` (throwError . toException @SomeException)) >>= k
Read (FromHandle handle) k -> (readBlobsFromHandle handle `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k Read (FromPathPair paths) k -> (runBothWith readFilePair paths `catchIO` (throwError . toException @SomeException)) >>= k
Read (FromPathPair paths) k -> (runBothWith readFilePair paths `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k Read (FromPairHandle handle) k -> (readBlobPairsFromHandle handle `catchIO` (throwError . toException @SomeException)) >>= k
Read (FromPairHandle handle) k -> (readBlobPairsFromHandle handle `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k ReadProject rootDir dir language excludeDirs k -> (readProjectFromPaths rootDir dir language excludeDirs `catchIO` (throwError . toException @SomeException)) >>= k
ReadProject rootDir dir language excludeDirs k -> (readProjectFromPaths rootDir dir language excludeDirs `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k FindFiles dir exts excludeDirs k -> (findFilesInDir dir exts excludeDirs `catchIO` (throwError . toException @SomeException)) >>= k
FindFiles dir exts excludeDirs k -> (findFilesInDir dir exts excludeDirs `catchIO` (throwError . toException @SomeException)) >>= runFilesC . k Write (ToPath path) builder k -> liftIO (IO.withBinaryFile path IO.WriteMode (`B.hPutBuilder` builder)) >> k
Write (ToPath path) builder k -> liftIO (IO.withBinaryFile path IO.WriteMode (`B.hPutBuilder` builder)) >> runFilesC k Write (ToHandle (WriteHandle handle)) builder k -> liftIO (B.hPutBuilder handle builder) >> k
Write (ToHandle (WriteHandle handle)) builder k -> liftIO (B.hPutBuilder handle builder) >> runFilesC k) eff (R other) = FilesC (eff (handleCoercible other))
readBlob :: (Member Files sig, Carrier sig m) => File -> m Blob readBlob :: (Member Files sig, Carrier sig m) => File -> m Blob
readBlob file = send (Read (FromPath file) ret) readBlob file = send (Read (FromPath file) pure)
-- | A task which reads a list of 'Blob's from a 'Handle' or a list of 'FilePath's optionally paired with 'Language's. -- | A task which reads a list of 'Blob's from a 'Handle' or a list of 'FilePath's optionally paired with 'Language's.
readBlobs :: (Member Files sig, Carrier sig m, Applicative m) => Either (Handle 'IO.ReadMode) [File] -> m [Blob] readBlobs :: (Member Files sig, Carrier sig m) => Either (Handle 'IO.ReadMode) [File] -> m [Blob]
readBlobs (Left handle) = send (Read (FromHandle handle) ret) readBlobs (Left handle) = send (Read (FromHandle handle) pure)
readBlobs (Right paths) = traverse (send . flip Read ret . FromPath) paths readBlobs (Right paths) = traverse (send . flip Read pure . FromPath) paths
-- | A task which reads a list of pairs of 'Blob's from a 'Handle' or a list of pairs of 'FilePath's optionally paired with 'Language's. -- | A task which reads a list of pairs of 'Blob's from a 'Handle' or a list of pairs of 'FilePath's optionally paired with 'Language's.
readBlobPairs :: (Member Files sig, Carrier sig m, Applicative m) => Either (Handle 'IO.ReadMode) [Both File] -> m [BlobPair] readBlobPairs :: (Member Files sig, Carrier sig m) => Either (Handle 'IO.ReadMode) [Both File] -> m [BlobPair]
readBlobPairs (Left handle) = send (Read (FromPairHandle handle) ret) readBlobPairs (Left handle) = send (Read (FromPairHandle handle) pure)
readBlobPairs (Right paths) = traverse (send . flip Read ret . FromPathPair) paths readBlobPairs (Right paths) = traverse (send . flip Read pure . FromPathPair) paths
readProject :: (Member Files sig, Carrier sig m) => Maybe FilePath -> FilePath -> Language -> [FilePath] -> m Project readProject :: (Member Files sig, Carrier sig m) => Maybe FilePath -> FilePath -> Language -> [FilePath] -> m Project
readProject rootDir dir lang excludeDirs = send (ReadProject rootDir dir lang excludeDirs ret) readProject rootDir dir lang excludeDirs = send (ReadProject rootDir dir lang excludeDirs pure)
findFiles :: (Member Files sig, Carrier sig m) => FilePath -> [String] -> [FilePath] -> m [FilePath] findFiles :: (Member Files sig, Carrier sig m) => FilePath -> [String] -> [FilePath] -> m [FilePath]
findFiles dir exts paths = send (FindFiles dir exts paths ret) findFiles dir exts paths = send (FindFiles dir exts paths pure)
-- | A task which writes a 'B.Builder' to a 'Handle' or a 'FilePath'. -- | A task which writes a 'B.Builder' to a 'Handle' or a 'FilePath'.
write :: (Member Files sig, Carrier sig m) => Destination -> B.Builder -> m () write :: (Member Files sig, Carrier sig m) => Destination -> B.Builder -> m ()
write dest builder = send (Write dest builder (ret ())) write dest builder = send (Write dest builder (pure ()))
-- | Generalize 'Exc.catch' to other 'MonadIO' contexts for the handler and result. -- | Generalize 'Exc.catch' to other 'MonadIO' contexts for the handler and result.

View File

@ -1,4 +1,4 @@
{-# LANGUAGE GADTs, KindSignatures, LambdaCase, RankNTypes, TypeOperators, UndecidableInstances #-} {-# LANGUAGE DerivingStrategies, GADTs, GeneralizedNewtypeDeriving, KindSignatures, RankNTypes, TypeOperators, UndecidableInstances #-}
module Semantic.Telemetry module Semantic.Telemetry
( (
-- Async telemetry interface -- Async telemetry interface
@ -52,6 +52,7 @@ module Semantic.Telemetry
import Control.Effect import Control.Effect
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Reader
import Control.Effect.Sum import Control.Effect.Sum
import Control.Exception import Control.Exception
import Control.Monad.IO.Class import Control.Monad.IO.Class
@ -121,11 +122,11 @@ queueStat q = liftIO . writeAsyncQueue q
-- | A task which logs a message at a specific log level to stderr. -- | A task which logs a message at a specific log level to stderr.
writeLog :: (Member Telemetry sig, Carrier sig m) => Level -> String -> [(String, String)] -> m () writeLog :: (Member Telemetry sig, Carrier sig m) => Level -> String -> [(String, String)] -> m ()
writeLog level message pairs = send (WriteLog level message pairs (ret ())) writeLog level message pairs = send (WriteLog level message pairs (pure ()))
-- | A task which writes a stat. -- | A task which writes a stat.
writeStat :: (Member Telemetry sig, Carrier sig m) => Stat -> m () writeStat :: (Member Telemetry sig, Carrier sig m) => Stat -> m ()
writeStat stat = send (WriteStat stat (ret ())) writeStat stat = send (WriteStat stat (pure ()))
-- | A task which measures and stats the timing of another task. -- | A task which measures and stats the timing of another task.
time :: (Member Telemetry sig, Carrier sig m, MonadIO m) => String -> [(String, String)] -> m output -> m output time :: (Member Telemetry sig, Carrier sig m, MonadIO m) => String -> [(String, String)] -> m output -> m output
@ -151,26 +152,28 @@ instance Effect Telemetry where
handle state handler (WriteLog level message pairs k) = WriteLog level message pairs (handler (k <$ state)) handle state handler (WriteLog level message pairs k) = WriteLog level message pairs (handler (k <$ state))
-- | Run a 'Telemetry' effect by expecting a 'Reader' of 'Queue's to write stats and logs to. -- | Run a 'Telemetry' effect by expecting a 'Reader' of 'Queue's to write stats and logs to.
runTelemetry :: (Carrier sig m, MonadIO m) => LogQueue -> StatQueue -> Eff (TelemetryC m) a -> m a runTelemetry :: LogQueue -> StatQueue -> TelemetryC m a -> m a
runTelemetry logger statter = flip runTelemetryC (logger, statter) . interpret runTelemetry logger statter = runReader (logger, statter) . runTelemetryC
newtype TelemetryC m a = TelemetryC { runTelemetryC :: (LogQueue, StatQueue) -> m a } newtype TelemetryC m a = TelemetryC { runTelemetryC :: ReaderC (LogQueue, StatQueue) m a }
deriving (Applicative, Functor, Monad, MonadIO)
instance (Carrier sig m, MonadIO m) => Carrier (Telemetry :+: sig) (TelemetryC m) where instance (Carrier sig m, MonadIO m) => Carrier (Telemetry :+: sig) (TelemetryC m) where
ret = TelemetryC . const . ret eff (L op) = do
eff op = TelemetryC (\ queues -> handleSum (eff . handleReader queues runTelemetryC) (\case queues <- TelemetryC ask
WriteStat stat k -> queueStat (snd queues) stat *> runTelemetryC k queues case op of
WriteLog level message pairs k -> queueLogMessage (fst queues) level message pairs *> runTelemetryC k queues) op) WriteStat stat k -> queueStat (snd queues) stat *> k
WriteLog level message pairs k -> queueLogMessage (fst queues) level message pairs *> k
eff (R other) = TelemetryC (eff (R (handleCoercible other)))
-- | Run a 'Telemetry' effect by ignoring statting/logging. -- | Run a 'Telemetry' effect by ignoring statting/logging.
ignoreTelemetry :: Carrier sig m => Eff (IgnoreTelemetryC m) a -> m a ignoreTelemetry :: IgnoreTelemetryC m a -> m a
ignoreTelemetry = runIgnoreTelemetryC . interpret ignoreTelemetry = runIgnoreTelemetryC
newtype IgnoreTelemetryC m a = IgnoreTelemetryC { runIgnoreTelemetryC :: m a } newtype IgnoreTelemetryC m a = IgnoreTelemetryC { runIgnoreTelemetryC :: m a }
deriving (Applicative, Functor, Monad)
instance Carrier sig m => Carrier (Telemetry :+: sig) (IgnoreTelemetryC m) where instance Carrier sig m => Carrier (Telemetry :+: sig) (IgnoreTelemetryC m) where
ret = IgnoreTelemetryC . ret eff (R other) = IgnoreTelemetryC . eff . handleCoercible $ other
eff = handleSum (IgnoreTelemetryC . eff . handlePure runIgnoreTelemetryC) (\case eff (L (WriteStat _ k)) = k
WriteStat _ k -> k eff (L (WriteLog _ _ _ k)) = k
WriteLog _ _ _ k -> k)

View File

@ -1,4 +1,4 @@
{-# LANGUAGE ExistentialQuantification, TypeOperators, RankNTypes, UndecidableInstances #-} {-# LANGUAGE ExistentialQuantification, GeneralizedNewtypeDeriving, TypeOperators, RankNTypes, UndecidableInstances #-}
module Semantic.Timeout module Semantic.Timeout
( timeout ( timeout
, Timeout , Timeout
@ -9,6 +9,7 @@ module Semantic.Timeout
import Control.Effect import Control.Effect
import Control.Effect.Carrier import Control.Effect.Carrier
import Control.Effect.Reader
import Control.Effect.Sum import Control.Effect.Sum
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Data.Duration import Data.Duration
@ -18,7 +19,7 @@ import qualified System.Timeout as System
-- within the specified duration. Uses 'System.Timeout.timeout' so all caveats -- within the specified duration. Uses 'System.Timeout.timeout' so all caveats
-- about not operating over FFI boundaries apply. -- about not operating over FFI boundaries apply.
timeout :: (Member Timeout sig, Carrier sig m) => Duration -> m output -> m (Maybe output) timeout :: (Member Timeout sig, Carrier sig m) => Duration -> m output -> m (Maybe output)
timeout n = send . flip (Timeout n) ret timeout n = send . flip (Timeout n) pure
-- | 'Timeout' effects run other effects, aborting them if they exceed the -- | 'Timeout' effects run other effects, aborting them if they exceed the
-- specified duration. -- specified duration.
@ -33,20 +34,22 @@ instance HFunctor Timeout where
instance Effect Timeout where instance Effect Timeout where
handle state handler (Timeout n task k) = Timeout n (handler (task <$ state)) (handler . maybe (k Nothing <$ state) (fmap (k . Just))) handle state handler (Timeout n task k) = Timeout n (handler (task <$ state)) (handler . maybe (k Nothing <$ state) (fmap (k . Just)))
-- | Evaulate a 'Timeoute' effect. -- | Evaulate a 'Timeout' effect.
runTimeout :: (Carrier sig m, MonadIO m) runTimeout :: (forall x . m x -> IO x)
=> (forall x . m x -> IO x) -> TimeoutC m a
-> Eff (TimeoutC m) a
-> m a -> m a
runTimeout handler = runTimeoutC handler . interpret runTimeout handler = runReader (Handler handler) . runTimeoutC
newtype TimeoutC m a = TimeoutC ((forall x . m x -> IO x) -> m a) newtype Handler m = Handler (forall x . m x -> IO x)
runTimeoutC :: (forall x . m x -> IO x) -> TimeoutC m a -> m a runHandler :: Handler m -> TimeoutC m a -> IO a
runTimeoutC f (TimeoutC m) = m f runHandler h@(Handler handler) = handler . runReader h . runTimeoutC
newtype TimeoutC m a = TimeoutC { runTimeoutC :: ReaderC (Handler m) m a }
deriving (Functor, Applicative, Monad, MonadIO)
instance (Carrier sig m, MonadIO m) => Carrier (Timeout :+: sig) (TimeoutC m) where instance (Carrier sig m, MonadIO m) => Carrier (Timeout :+: sig) (TimeoutC m) where
ret a = TimeoutC (const (ret a)) eff (L (Timeout n task k)) = do
eff op = TimeoutC (\ handler -> handleSum handler <- TimeoutC ask
(eff . handlePure (runTimeoutC handler)) liftIO (System.timeout (toMicroseconds n) (runHandler handler task)) >>= k
(\ (Timeout n task k) -> liftIO (System.timeout (toMicroseconds n) (handler (runTimeoutC handler task))) >>= runTimeoutC handler . k) op) eff (R other) = TimeoutC (eff (R (handleCoercible other)))

View File

@ -58,40 +58,30 @@ justEvaluating :: Evaluator
(Value term Precise) (Value term Precise)
(ResumableC (ResumableC
(BaseError (ValueError term Precise)) (BaseError (ValueError term Precise))
(Eff
(ResumableC (ResumableC
(BaseError (AddressError Precise (Value term Precise))) (BaseError (AddressError Precise (Value term Precise)))
(Eff
(ResumableC (ResumableC
(BaseError ResolutionError) (BaseError ResolutionError)
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(EvalError term Precise (Value term Precise))) (EvalError term Precise (Value term Precise)))
(Eff
(ResumableC (ResumableC
(BaseError (HeapError Precise)) (BaseError (HeapError Precise))
(Eff
(ResumableC (ResumableC
(BaseError (ScopeError Precise)) (BaseError (ScopeError Precise))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(UnspecializedError (UnspecializedError
Precise (Value term Precise))) Precise (Value term Precise)))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(LoadError (LoadError
Precise Precise
(Value term Precise))) (Value term Precise)))
(Eff
(FreshC (FreshC
(Eff
(StateC (StateC
(ScopeGraph (ScopeGraph
Precise) Precise)
(Eff
(StateC (StateC
(Heap (Heap
Precise Precise
@ -99,11 +89,9 @@ justEvaluating :: Evaluator
(Value (Value
term term
Precise)) Precise))
(Eff
(TraceByPrintingC (TraceByPrintingC
(Eff
(LiftC (LiftC
IO))))))))))))))))))))))))) IO)))))))))))))
result result
-> IO -> IO
(Heap Precise Precise (Value term Precise), (Heap Precise Precise (Value term Precise),
@ -148,18 +136,18 @@ justEvaluatingCatchingErrors :: ( hole ~ Hole (Maybe Name) Precise
value value
(ResumableWithC (ResumableWithC
(BaseError (ValueError term hole)) (BaseError (ValueError term hole))
(Eff (ResumableWithC (BaseError (AddressError hole value)) (ResumableWithC (BaseError (AddressError hole value))
(Eff (ResumableWithC (BaseError ResolutionError) (ResumableWithC (BaseError ResolutionError)
(Eff (ResumableWithC (BaseError (EvalError term hole value)) (ResumableWithC (BaseError (EvalError term hole value))
(Eff (ResumableWithC (BaseError (HeapError hole)) (ResumableWithC (BaseError (HeapError hole))
(Eff (ResumableWithC (BaseError (ScopeError hole)) (ResumableWithC (BaseError (ScopeError hole))
(Eff (ResumableWithC (BaseError (UnspecializedError hole value)) (ResumableWithC (BaseError (UnspecializedError hole value))
(Eff (ResumableWithC (BaseError (LoadError hole value)) (ResumableWithC (BaseError (LoadError hole value))
(Eff (FreshC (FreshC
(Eff (StateC (ScopeGraph hole) (StateC (ScopeGraph hole)
(Eff (StateC (Heap hole hole (Concrete.Value (Quieterm (Sum lang) Location) (Hole (Maybe Name) Precise))) (StateC (Heap hole hole (Concrete.Value (Quieterm (Sum lang) Location) (Hole (Maybe Name) Precise)))
(Eff (TraceByPrintingC (TraceByPrintingC
(Eff (LiftC IO))))))))))))))))))))))))) a (LiftC IO))))))))))))) a
-> IO (Heap hole hole value, (ScopeGraph hole, a)) -> IO (Heap hole hole value, (ScopeGraph hole, a))
justEvaluatingCatchingErrors justEvaluatingCatchingErrors
= runM = runM
@ -185,84 +173,66 @@ checking
(ResumableC (ResumableC
(BaseError (BaseError
Type.TypeError) Type.TypeError)
(Eff
(StateC (StateC
Type.TypeMap Type.TypeMap
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(AddressError (AddressError
Monovariant Monovariant
Type.Type)) Type.Type))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(EvalError (EvalError
term term
Monovariant Monovariant
Type.Type)) Type.Type))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
ResolutionError) ResolutionError)
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(HeapError (HeapError
Monovariant)) Monovariant))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(ScopeError (ScopeError
Monovariant)) Monovariant))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(UnspecializedError (UnspecializedError
Monovariant Monovariant
Type.Type)) Type.Type))
(Eff
(ResumableC (ResumableC
(BaseError (BaseError
(LoadError (LoadError
Monovariant Monovariant
Type.Type)) Type.Type))
(Eff
(ReaderC (ReaderC
(Live (Live
Monovariant) Monovariant)
(Eff (NonDetC
(AltC
[]
(Eff
(ReaderC (ReaderC
(Cache (Cache
term term
Monovariant Monovariant
Type.Type) Type.Type)
(Eff
(StateC (StateC
(Cache (Cache
term term
Monovariant Monovariant
Type.Type) Type.Type)
(Eff
(FreshC (FreshC
(Eff
(StateC (StateC
(ScopeGraph (ScopeGraph
Monovariant) Monovariant)
(Eff
(StateC (StateC
(Heap (Heap
Monovariant Monovariant
Monovariant Monovariant
Type.Type) Type.Type)
(Eff
(TraceByPrintingC (TraceByPrintingC
(Eff
(LiftC (LiftC
IO))))))))))))))))))))))))))))))))))) IO))))))))))))))))))
result result
-> IO -> IO
(Heap (Heap
@ -567,17 +537,18 @@ callGraphRubyProject :: [FilePath] -> IO (Graph ControlFlowVertex, [Module ()])
callGraphRubyProject = callGraphProject rubyParser (Proxy @'Language.Ruby) callGraphRubyProject = callGraphProject rubyParser (Proxy @'Language.Ruby)
type EvalEffects qterm err = ResumableC (BaseError err) type EvalEffects qterm err = ResumableC (BaseError err)
(Eff (ResumableC (BaseError (AddressError Precise (Value qterm Precise))) (ResumableC (BaseError (AddressError Precise (Value qterm Precise)))
(Eff (ResumableC (BaseError ResolutionError) (ResumableC (BaseError ResolutionError)
(Eff (ResumableC (BaseError (EvalError qterm Precise (Value qterm Precise))) (ResumableC (BaseError (EvalError qterm Precise (Value qterm Precise)))
(Eff (ResumableC (BaseError (HeapError Precise)) (ResumableC (BaseError (HeapError Precise))
(Eff (ResumableC (BaseError (ScopeError Precise)) (ResumableC (BaseError (ScopeError Precise))
(Eff (ResumableC (BaseError (UnspecializedError Precise (Value qterm Precise))) (ResumableC (BaseError (UnspecializedError Precise (Value qterm Precise)))
(Eff (ResumableC (BaseError (LoadError Precise (Value qterm Precise))) (ResumableC (BaseError (LoadError Precise (Value qterm Precise)))
(Eff (FreshC (Eff (StateC (ScopeGraph Precise) (FreshC
(Eff (StateC (Heap Precise Precise (Value qterm Precise)) (StateC (ScopeGraph Precise)
(Eff (TraceByPrintingC (StateC (Heap Precise Precise (Value qterm Precise))
(Eff (LiftC IO)))))))))))))))))))))))) (TraceByPrintingC
(LiftC IO))))))))))))
type LanguageSyntax lang syntax = ( Language.SLanguage lang type LanguageSyntax lang syntax = ( Language.SLanguage lang
, HasPrelude lang , HasPrelude lang
@ -646,18 +617,18 @@ evaluateProjectForScopeGraph :: ( term ~ Term (Sum syntax) Location
-> IO (Evaluator qterm address -> IO (Evaluator qterm address
(Value qterm address) (Value qterm address)
(ResumableWithC (BaseError (ValueError qterm address)) (ResumableWithC (BaseError (ValueError qterm address))
(Eff (ResumableWithC (BaseError (AddressError address (Value qterm address))) (ResumableWithC (BaseError (AddressError address (Value qterm address)))
(Eff (ResumableWithC (BaseError ResolutionError) (ResumableWithC (BaseError ResolutionError)
(Eff (ResumableWithC (BaseError (EvalError qterm address (Value qterm address))) (ResumableWithC (BaseError (EvalError qterm address (Value qterm address)))
(Eff (ResumableWithC (BaseError (HeapError address)) (ResumableWithC (BaseError (HeapError address))
(Eff (ResumableWithC (BaseError (ScopeError address)) (ResumableWithC (BaseError (ScopeError address))
(Eff (ResumableWithC (BaseError (UnspecializedError address (Value qterm address))) (ResumableWithC (BaseError (UnspecializedError address (Value qterm address)))
(Eff (ResumableWithC (BaseError (LoadError address (Value qterm address))) (ResumableWithC (BaseError (LoadError address (Value qterm address)))
(Eff (FreshC (FreshC
(Eff (StateC (ScopeGraph address) (StateC (ScopeGraph address)
(Eff (StateC (Heap address address (Value qterm address)) (StateC (Heap address address (Value qterm address))
(Eff (TraceByPrintingC (TraceByPrintingC
(Eff (LiftC IO))))))))))))))))))))))))) (LiftC IO)))))))))))))
(ModuleTable (Module (ModuleTable (Module
(ModuleResult address (Value qterm address))))) (ModuleResult address (Value qterm address)))))
evaluateProjectForScopeGraph proxy parser project = runTask' $ do evaluateProjectForScopeGraph proxy parser project = runTask' $ do
@ -681,22 +652,23 @@ evaluateProjectWithCaching :: ( term ~ Term (Sum syntax) Location
-> FilePath -> FilePath
-> IO (Evaluator qterm Monovariant Type -> IO (Evaluator qterm Monovariant Type
(ResumableC (BaseError Type.TypeError) (ResumableC (BaseError Type.TypeError)
(Eff (StateC TypeMap (StateC TypeMap
(Eff (ResumableC (BaseError (AddressError Monovariant Type)) (ResumableC (BaseError (AddressError Monovariant Type))
(Eff (ResumableC (BaseError (EvalError qterm Monovariant Type)) (ResumableC (BaseError (EvalError qterm Monovariant Type))
(Eff (ResumableC (BaseError ResolutionError) (ResumableC (BaseError ResolutionError)
(Eff (ResumableC (BaseError (HeapError Monovariant)) (ResumableC (BaseError (HeapError Monovariant))
(Eff (ResumableC (BaseError (ScopeError Monovariant)) (ResumableC (BaseError (ScopeError Monovariant))
(Eff (ResumableC (BaseError (UnspecializedError Monovariant Type)) (ResumableC (BaseError (UnspecializedError Monovariant Type))
(Eff (ResumableC (BaseError (LoadError Monovariant Type)) (ResumableC (BaseError (LoadError Monovariant Type))
(Eff (ReaderC (Live Monovariant) (ReaderC (Live Monovariant)
(Eff (AltC [] (NonDetC
(Eff (ReaderC (Analysis.Abstract.Caching.FlowSensitive.Cache (Data.Quieterm.Quieterm (Sum syntax) Data.Location.Location) Monovariant Type) (ReaderC (Analysis.Abstract.Caching.FlowSensitive.Cache (Data.Quieterm.Quieterm (Sum syntax) Data.Location.Location) Monovariant Type)
(Eff (StateC (Analysis.Abstract.Caching.FlowSensitive.Cache (Data.Quieterm.Quieterm (Sum syntax) Data.Location.Location) Monovariant Type) (StateC (Analysis.Abstract.Caching.FlowSensitive.Cache (Data.Quieterm.Quieterm (Sum syntax) Data.Location.Location) Monovariant Type)
(Eff (FreshC (FreshC
(Eff (StateC (ScopeGraph Monovariant) (StateC (ScopeGraph Monovariant)
(Eff (StateC (Heap Monovariant Monovariant Type) (StateC (Heap Monovariant Monovariant Type)
(Eff (TraceByPrintingC (Eff (LiftC IO))))))))))))))))))))))))))))))))))) (TraceByPrintingC
(LiftC IO))))))))))))))))))
(ModuleTable (Module (ModuleResult Monovariant Type)))) (ModuleTable (Module (ModuleResult Monovariant Type))))
evaluateProjectWithCaching proxy parser path = runTask' $ do evaluateProjectWithCaching proxy parser path = runTask' $ do
project <- readProject Nothing path (Language.reflect proxy) [] project <- readProject Nothing path (Language.reflect proxy) []

View File

@ -38,9 +38,8 @@ runTagging blob tree
type ContextToken = (Text, Maybe Range) type ContextToken = (Text, Maybe Range)
type Contextualizer type Contextualizer
= Eff (StateC [ContextToken] = StateC [ContextToken]
( Eff (ErrorC TranslationError ( ErrorC TranslationError VoidC)
( Eff VoidC))))
contextualizing :: Blob -> Machine.ProcessT Contextualizer Token Tag contextualizing :: Blob -> Machine.ProcessT Contextualizer Token Tag
contextualizing Blob{..} = repeatedly $ await >>= \case contextualizing Blob{..} = repeatedly $ await >>= \case

View File

@ -69,7 +69,7 @@ evaluate
. runValueError . runValueError
. runAddressError . runAddressError
. runEvalError . runEvalError
. runDeref @Val . runDeref @SpecEff
. runAllocator . runAllocator
. runReturn . runReturn
. runLoopControl . runLoopControl
@ -85,29 +85,29 @@ reassociate = mergeErrors . mergeErrors . mergeErrors . mergeErrors . mergeError
type Val = Value SpecEff Precise type Val = Value SpecEff Precise
newtype SpecEff = SpecEff newtype SpecEff = SpecEff
{ runSpecEff :: Evaluator SpecEff Precise Val (FunctionC SpecEff Precise Val { runSpecEff :: Evaluator SpecEff Precise Val (FunctionC SpecEff Precise Val
(Eff (BooleanC Val (BooleanC Val
(Eff (NumericC Val (NumericC Val
(Eff (ErrorC (LoopControl Val) (ErrorC (LoopControl Val)
(Eff (ErrorC (Return Val) (ErrorC (Return Val)
(Eff (AllocatorC Precise (AllocatorC Precise
(Eff (DerefC Precise Val (DerefC Precise Val
(Eff (ResumableC (BaseError (EvalError SpecEff Precise Val)) (ResumableC (BaseError (EvalError SpecEff Precise Val))
(Eff (ResumableC (BaseError (AddressError Precise Val)) (ResumableC (BaseError (AddressError Precise Val))
(Eff (ResumableC (BaseError (ValueError SpecEff Precise)) (ResumableC (BaseError (ValueError SpecEff Precise))
(Eff (ResumableC (BaseError (HeapError Precise)) (ResumableC (BaseError (HeapError Precise))
(Eff (ResumableC (BaseError (ScopeError Precise)) (ResumableC (BaseError (ScopeError Precise))
(Eff (ReaderC (CurrentFrame Precise) (ReaderC (CurrentFrame Precise)
(Eff (ReaderC (CurrentScope Precise) (ReaderC (CurrentScope Precise)
(Eff (AllocatorC Precise (AllocatorC Precise
(Eff (ReaderC Span (ReaderC Span
(Eff (StateC Span (StateC Span
(Eff (ReaderC ModuleInfo (ReaderC ModuleInfo
(Eff (ReaderC PackageInfo (ReaderC PackageInfo
(Eff (FreshC (FreshC
(Eff (StateC (Heap Precise Precise Val) (StateC (Heap Precise Precise Val)
(Eff (StateC (ScopeGraph Precise) (StateC (ScopeGraph Precise)
(Eff (TraceByIgnoringC (TraceByIgnoringC
(Eff (LiftC IO))))))))))))))))))))))))))))))))))))))))))))))) (LiftC IO))))))))))))))))))))))))
Val Val
} }

View File

@ -117,19 +117,19 @@ runTaskOrDie :: TaskEff a -> IO a
runTaskOrDie task = runTaskWithOptions defaultOptions { optionsLogLevel = Nothing } task >>= either (die . displayException) pure runTaskOrDie task = runTaskWithOptions defaultOptions { optionsLogLevel = Nothing } task >>= either (die . displayException) pure
type TestEvaluatingC term type TestEvaluatingC term
= ResumableC (BaseError (AddressError Precise (Val term))) (Eff = ResumableC (BaseError (AddressError Precise (Val term)))
( ResumableC (BaseError (ValueError term Precise)) (Eff ( ResumableC (BaseError (ValueError term Precise))
( ResumableC (BaseError ResolutionError) (Eff ( ResumableC (BaseError ResolutionError)
( ResumableC (BaseError (EvalError term Precise (Val term))) (Eff ( ResumableC (BaseError (EvalError term Precise (Val term)))
( ResumableC (BaseError (HeapError Precise)) (Eff ( ResumableC (BaseError (HeapError Precise))
( ResumableC (BaseError (ScopeError Precise)) (Eff ( ResumableC (BaseError (ScopeError Precise))
( ResumableC (BaseError (UnspecializedError Precise (Val term))) (Eff ( ResumableC (BaseError (UnspecializedError Precise (Val term)))
( ResumableC (BaseError (LoadError Precise (Val term))) (Eff ( ResumableC (BaseError (LoadError Precise (Val term)))
( StateC (Heap Precise Precise (Val term)) (Eff ( StateC (Heap Precise Precise (Val term))
( StateC (ScopeGraph Precise) (Eff ( StateC (ScopeGraph Precise)
( FreshC (Eff ( FreshC
( TraceByIgnoringC (Eff ( TraceByIgnoringC
( LiftC IO)))))))))))))))))))))))) ( LiftC IO))))))))))))
type TestEvaluatingErrors term type TestEvaluatingErrors term
= '[ BaseError (AddressError Precise (Val term)) = '[ BaseError (AddressError Precise (Val term))
, BaseError (ValueError term Precise) , BaseError (ValueError term Precise)

@ -1 +1 @@
Subproject commit f7e6b37ab92a001b080f7749d3cc45ac3214f699 Subproject commit 17b0a846aa50fd0dea157624c031a550d8edd469