mirror of
https://github.com/github/semantic.git
synced 2024-12-30 02:14:20 +03:00
Merge branch 'master' into fix-benchmarks
This commit is contained in:
commit
d5be7ee842
@ -19,7 +19,8 @@ library
|
|||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
-- Analyses & term annotations
|
-- Analyses & term annotations
|
||||||
Analysis.Abstract.Caching
|
Analysis.Abstract.Caching.FlowInsensitive
|
||||||
|
, Analysis.Abstract.Caching.FlowSensitive
|
||||||
, Analysis.Abstract.Collecting
|
, Analysis.Abstract.Collecting
|
||||||
, Analysis.Abstract.Dead
|
, Analysis.Abstract.Dead
|
||||||
, Analysis.Abstract.Graph
|
, Analysis.Abstract.Graph
|
||||||
@ -35,7 +36,6 @@ library
|
|||||||
, Assigning.Assignment.Table
|
, Assigning.Assignment.Table
|
||||||
-- Control structures & interfaces for abstract interpretation
|
-- Control structures & interfaces for abstract interpretation
|
||||||
, Control.Abstract
|
, Control.Abstract
|
||||||
, Control.Abstract.Configuration
|
|
||||||
, Control.Abstract.Context
|
, Control.Abstract.Context
|
||||||
, Control.Abstract.Environment
|
, Control.Abstract.Environment
|
||||||
, Control.Abstract.Evaluator
|
, Control.Abstract.Evaluator
|
||||||
@ -46,6 +46,7 @@ library
|
|||||||
, Control.Abstract.Primitive
|
, Control.Abstract.Primitive
|
||||||
, Control.Abstract.PythonPackage
|
, Control.Abstract.PythonPackage
|
||||||
, Control.Abstract.Roots
|
, Control.Abstract.Roots
|
||||||
|
, Control.Abstract.ScopeGraph
|
||||||
, Control.Abstract.TermEvaluator
|
, Control.Abstract.TermEvaluator
|
||||||
, Control.Abstract.Value
|
, Control.Abstract.Value
|
||||||
-- Datatypes for abstract interpretation
|
-- Datatypes for abstract interpretation
|
||||||
@ -54,8 +55,6 @@ library
|
|||||||
, Data.Abstract.Address.Monovariant
|
, Data.Abstract.Address.Monovariant
|
||||||
, Data.Abstract.Address.Precise
|
, Data.Abstract.Address.Precise
|
||||||
, Data.Abstract.BaseError
|
, Data.Abstract.BaseError
|
||||||
, Data.Abstract.Cache
|
|
||||||
, Data.Abstract.Configuration
|
|
||||||
, Data.Abstract.Declarations
|
, Data.Abstract.Declarations
|
||||||
, Data.Abstract.Environment
|
, Data.Abstract.Environment
|
||||||
, Data.Abstract.Evaluatable
|
, Data.Abstract.Evaluatable
|
||||||
@ -70,6 +69,7 @@ library
|
|||||||
, Data.Abstract.Package
|
, Data.Abstract.Package
|
||||||
, Data.Abstract.Path
|
, Data.Abstract.Path
|
||||||
, Data.Abstract.Ref
|
, Data.Abstract.Ref
|
||||||
|
, Data.Abstract.ScopeGraph
|
||||||
, Data.Abstract.Value.Abstract
|
, Data.Abstract.Value.Abstract
|
||||||
, Data.Abstract.Value.Concrete
|
, Data.Abstract.Value.Concrete
|
||||||
, Data.Abstract.Value.Type
|
, Data.Abstract.Value.Type
|
||||||
|
173
src/Analysis/Abstract/Caching/FlowInsensitive.hs
Normal file
173
src/Analysis/Abstract/Caching/FlowInsensitive.hs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, TypeOperators #-}
|
||||||
|
module Analysis.Abstract.Caching.FlowInsensitive
|
||||||
|
( cachingTerms
|
||||||
|
, convergingModules
|
||||||
|
, caching
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Abstract
|
||||||
|
import Data.Abstract.BaseError
|
||||||
|
import Data.Abstract.Environment
|
||||||
|
import Data.Abstract.Module
|
||||||
|
import Data.Abstract.Ref
|
||||||
|
import Data.Map.Monoidal as Monoidal
|
||||||
|
import Prologue
|
||||||
|
|
||||||
|
-- | Look up the set of values for a given configuration in the in-cache.
|
||||||
|
consultOracle :: (Member (Reader (Cache term address)) effects, Ord address, Ord term)
|
||||||
|
=> Configuration term address
|
||||||
|
-> TermEvaluator term address value effects (Set (ValueRef address))
|
||||||
|
consultOracle configuration = fromMaybe mempty . cacheLookup configuration <$> ask
|
||||||
|
|
||||||
|
-- | Run an action with the given in-cache.
|
||||||
|
withOracle :: Member (Reader (Cache term address)) effects
|
||||||
|
=> Cache term address
|
||||||
|
-> TermEvaluator term address value effects a
|
||||||
|
-> TermEvaluator term address value effects a
|
||||||
|
withOracle cache = local (const cache)
|
||||||
|
|
||||||
|
|
||||||
|
-- | Look up the set of values for a given configuration in the out-cache.
|
||||||
|
lookupCache :: (Member (State (Cache term address)) effects, Ord address, Ord term)
|
||||||
|
=> Configuration term address
|
||||||
|
-> TermEvaluator term address value effects (Maybe (Set (ValueRef address)))
|
||||||
|
lookupCache configuration = cacheLookup configuration <$> get
|
||||||
|
|
||||||
|
-- | Run an action, caching its result and 'Heap' under the given configuration.
|
||||||
|
cachingConfiguration :: (Member (State (Cache term address)) effects, Ord address, Ord term)
|
||||||
|
=> Configuration term address
|
||||||
|
-> Set (ValueRef address)
|
||||||
|
-> TermEvaluator term address value effects (ValueRef address)
|
||||||
|
-> TermEvaluator term address value effects (ValueRef address)
|
||||||
|
cachingConfiguration configuration values action = do
|
||||||
|
modify' (cacheSet configuration values)
|
||||||
|
result <- action
|
||||||
|
result <$ modify' (cacheInsert configuration result)
|
||||||
|
|
||||||
|
putCache :: Member (State (Cache term address)) effects
|
||||||
|
=> Cache term address
|
||||||
|
-> TermEvaluator term address value effects ()
|
||||||
|
putCache = put
|
||||||
|
|
||||||
|
-- | Run an action starting from an empty out-cache, and return the out-cache afterwards.
|
||||||
|
isolateCache :: (Member (State (Cache term address)) effects, Member (State (Heap address value)) effects)
|
||||||
|
=> TermEvaluator term address value effects a
|
||||||
|
-> TermEvaluator term address value effects (Cache term address, Heap address value)
|
||||||
|
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.
|
||||||
|
cachingTerms :: ( Corecursive term
|
||||||
|
, Member (Env address) effects
|
||||||
|
, Member NonDet effects
|
||||||
|
, Member (Reader (Cache term address)) effects
|
||||||
|
, Member (Reader (Live address)) effects
|
||||||
|
, Member (State (Cache term address)) effects
|
||||||
|
, Ord address
|
||||||
|
, Ord term
|
||||||
|
)
|
||||||
|
=> SubtermAlgebra (Base term) term (TermEvaluator term address value effects (ValueRef address))
|
||||||
|
-> SubtermAlgebra (Base term) term (TermEvaluator term address value effects (ValueRef address))
|
||||||
|
cachingTerms recur term = do
|
||||||
|
c <- getConfiguration (embedSubterm term)
|
||||||
|
cached <- lookupCache c
|
||||||
|
case cached of
|
||||||
|
Just values -> scatter values
|
||||||
|
Nothing -> do
|
||||||
|
values <- consultOracle c
|
||||||
|
cachingConfiguration c values (recur term)
|
||||||
|
|
||||||
|
convergingModules :: ( AbstractValue address value effects
|
||||||
|
, Effects effects
|
||||||
|
, Eq value
|
||||||
|
, Member (Env address) effects
|
||||||
|
, Member Fresh effects
|
||||||
|
, Member NonDet effects
|
||||||
|
, Member (Reader (Cache term address)) effects
|
||||||
|
, Member (Reader (Live address)) effects
|
||||||
|
, Member (Reader ModuleInfo) effects
|
||||||
|
, Member (Reader Span) effects
|
||||||
|
, Member (Resumable (BaseError (EnvironmentError address))) effects
|
||||||
|
, Member (State (Cache term address)) effects
|
||||||
|
, Member (State (Heap address value)) effects
|
||||||
|
, Ord address
|
||||||
|
, Ord term
|
||||||
|
)
|
||||||
|
=> SubtermAlgebra Module term (TermEvaluator term address value effects address)
|
||||||
|
-> SubtermAlgebra Module term (TermEvaluator term address value effects address)
|
||||||
|
convergingModules recur m = do
|
||||||
|
c <- getConfiguration (subterm (moduleBody m))
|
||||||
|
heap <- TermEvaluator getHeap
|
||||||
|
-- Convergence here is predicated upon an Eq instance, not α-equivalence
|
||||||
|
(cache, _) <- converge (lowerBound, heap) (\ (prevCache, _) -> isolateCache $ do
|
||||||
|
TermEvaluator (putEvalContext (configurationContext c))
|
||||||
|
-- We need to reset fresh generation so that this invocation converges.
|
||||||
|
resetFresh 0 $
|
||||||
|
-- This is subtle: though the calling context supports nondeterminism, we want
|
||||||
|
-- to corral all the nondeterminism that happens in this @eval@ invocation, so
|
||||||
|
-- that it doesn't "leak" to the calling context and diverge (otherwise this
|
||||||
|
-- would never complete). We don’t need to use the values, so we 'gather' the
|
||||||
|
-- nondeterministic values into @()@.
|
||||||
|
withOracle prevCache (gatherM (const ()) (recur m)))
|
||||||
|
TermEvaluator (address =<< runTermEvaluator (maybe empty scatter (cacheLookup c cache)))
|
||||||
|
|
||||||
|
-- | Iterate a monadic action starting from some initial seed until the results converge.
|
||||||
|
--
|
||||||
|
-- This applies the Kleene fixed-point theorem to finitize a monotone action. cf https://en.wikipedia.org/wiki/Kleene_fixed-point_theorem
|
||||||
|
converge :: (Eq a, Monad m)
|
||||||
|
=> a -- ^ An initial seed value to iterate from.
|
||||||
|
-> (a -> m a) -- ^ A monadic action to perform at each iteration, starting from the result of the previous iteration or from the seed value for the first iteration.
|
||||||
|
-> m a -- ^ A computation producing the least fixed point (the first value at which the actions converge).
|
||||||
|
converge seed f = loop seed
|
||||||
|
where loop x = do
|
||||||
|
x' <- f x
|
||||||
|
if x' == x then
|
||||||
|
pure x
|
||||||
|
else
|
||||||
|
loop x'
|
||||||
|
|
||||||
|
-- | Nondeterministically write each of a collection of stores & return their associated results.
|
||||||
|
scatter :: (Foldable t, Member NonDet effects) => t (ValueRef address) -> TermEvaluator term address value effects (ValueRef address)
|
||||||
|
scatter = foldMapA pure
|
||||||
|
|
||||||
|
-- | Get the current 'Configuration' with a passed-in term.
|
||||||
|
getConfiguration :: (Member (Reader (Live address)) effects, Member (Env address) effects)
|
||||||
|
=> term
|
||||||
|
-> TermEvaluator term address value effects (Configuration term address)
|
||||||
|
getConfiguration term = Configuration term <$> TermEvaluator askRoots <*> TermEvaluator getEvalContext
|
||||||
|
|
||||||
|
|
||||||
|
caching :: Effects effects => TermEvaluator term address value (NonDet ': Reader (Cache term address) ': State (Cache term address) ': effects) a -> TermEvaluator term address value effects (Cache term address, [a])
|
||||||
|
caching
|
||||||
|
= runState lowerBound
|
||||||
|
. runReader lowerBound
|
||||||
|
. runNonDet
|
||||||
|
|
||||||
|
|
||||||
|
-- | A map of 'Configuration's to 'Set's of resulting values & 'Heap's.
|
||||||
|
newtype Cache term address = Cache { unCache :: Monoidal.Map (Configuration term address) (Set (ValueRef address)) }
|
||||||
|
deriving (Eq, Lower, Monoid, Ord, Reducer (Configuration term address, ValueRef address), Semigroup)
|
||||||
|
|
||||||
|
-- | A single point in a program’s execution.
|
||||||
|
data Configuration term address = Configuration
|
||||||
|
{ configurationTerm :: term -- ^ The “instruction,” i.e. the current term to evaluate.
|
||||||
|
, configurationRoots :: Live address -- ^ The set of rooted addresses.
|
||||||
|
, configurationContext :: EvalContext address -- ^ The evaluation context in 'configurationTerm'.
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
|
||||||
|
-- | Look up the resulting value & 'Heap' for a given 'Configuration'.
|
||||||
|
cacheLookup :: (Ord address, Ord term) => Configuration term address -> Cache term address -> Maybe (Set (ValueRef address))
|
||||||
|
cacheLookup key = Monoidal.lookup key . unCache
|
||||||
|
|
||||||
|
-- | Set the resulting value & 'Heap' for a given 'Configuration', overwriting any previous entry.
|
||||||
|
cacheSet :: (Ord address, Ord term) => Configuration term address -> Set (ValueRef address) -> Cache term address -> Cache term address
|
||||||
|
cacheSet key value = Cache . Monoidal.insert key value . unCache
|
||||||
|
|
||||||
|
-- | Insert the resulting value & 'Heap' for a given 'Configuration', appending onto any previous entry.
|
||||||
|
cacheInsert :: (Ord address, Ord term) => Configuration term address -> ValueRef address -> Cache term address -> Cache term address
|
||||||
|
cacheInsert = curry cons
|
||||||
|
|
||||||
|
instance (Show term, Show address) => Show (Cache term address) where
|
||||||
|
showsPrec d = showsUnaryWith showsPrec "Cache" d . map (second toList) . Monoidal.pairs . unCache
|
@ -1,17 +1,16 @@
|
|||||||
{-# LANGUAGE GADTs, TypeOperators #-}
|
{-# LANGUAGE ConstraintKinds, GADTs, GeneralizedNewtypeDeriving, TypeOperators #-}
|
||||||
module Analysis.Abstract.Caching
|
module Analysis.Abstract.Caching.FlowSensitive
|
||||||
( cachingTerms
|
( cachingTerms
|
||||||
, convergingModules
|
, convergingModules
|
||||||
, caching
|
, caching
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Abstract.Configuration
|
|
||||||
import Control.Abstract
|
import Control.Abstract
|
||||||
import Data.Abstract.Cache
|
|
||||||
import Data.Abstract.BaseError
|
import Data.Abstract.BaseError
|
||||||
import Data.Abstract.Environment
|
import Data.Abstract.Environment
|
||||||
import Data.Abstract.Module
|
import Data.Abstract.Module
|
||||||
import Data.Abstract.Ref
|
import Data.Abstract.Ref
|
||||||
|
import Data.Map.Monoidal as Monoidal
|
||||||
import Prologue
|
import Prologue
|
||||||
|
|
||||||
-- | Look up the set of values for a given configuration in the in-cache.
|
-- | Look up the set of values for a given configuration in the in-cache.
|
||||||
@ -129,9 +128,53 @@ converge seed f = loop seed
|
|||||||
scatter :: (Foldable t, Member NonDet effects, Member (State (Heap address value)) effects) => t (Cached address value) -> TermEvaluator term address value effects (ValueRef address)
|
scatter :: (Foldable t, Member NonDet effects, Member (State (Heap address value)) effects) => t (Cached address value) -> TermEvaluator term address value effects (ValueRef address)
|
||||||
scatter = foldMapA (\ (Cached value heap') -> TermEvaluator (putHeap heap') $> value)
|
scatter = foldMapA (\ (Cached value heap') -> TermEvaluator (putHeap heap') $> value)
|
||||||
|
|
||||||
|
-- | Get the current 'Configuration' with a passed-in term.
|
||||||
|
getConfiguration :: (Member (Reader (Live address)) effects, Member (Env address) effects, Member (State (Heap address value)) effects)
|
||||||
|
=> term
|
||||||
|
-> TermEvaluator term address value effects (Configuration term address value)
|
||||||
|
getConfiguration term = Configuration term <$> TermEvaluator askRoots <*> TermEvaluator getEvalContext <*> TermEvaluator getHeap
|
||||||
|
|
||||||
|
|
||||||
caching :: Effects effects => TermEvaluator term address value (NonDet ': Reader (Cache term address value) ': State (Cache term address value) ': effects) a -> TermEvaluator term address value effects (Cache term address value, [a])
|
caching :: Effects effects => TermEvaluator term address value (NonDet ': Reader (Cache term address value) ': State (Cache term address value) ': effects) a -> TermEvaluator term address value effects (Cache term address value, [a])
|
||||||
caching
|
caching
|
||||||
= runState lowerBound
|
= runState lowerBound
|
||||||
. runReader lowerBound
|
. runReader lowerBound
|
||||||
. runNonDet
|
. runNonDet
|
||||||
|
|
||||||
|
|
||||||
|
-- | A map of 'Configuration's to 'Set's of resulting values & 'Heap's.
|
||||||
|
newtype Cache term address value = Cache { unCache :: Monoidal.Map (Configuration term address value) (Set (Cached address value)) }
|
||||||
|
deriving (Eq, Lower, Monoid, Ord, Reducer (Configuration term address value, Cached address value), Semigroup)
|
||||||
|
|
||||||
|
-- | A single point in a program’s execution.
|
||||||
|
data Configuration term address value = Configuration
|
||||||
|
{ configurationTerm :: term -- ^ The “instruction,” i.e. the current term to evaluate.
|
||||||
|
, configurationRoots :: Live address -- ^ The set of rooted addresses.
|
||||||
|
, configurationContext :: EvalContext address -- ^ The evaluation context in 'configurationTerm'.
|
||||||
|
, configurationHeap :: Heap address value -- ^ The heap of values.
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
data Cached address value = Cached
|
||||||
|
{ cachedValue :: ValueRef address
|
||||||
|
, cachedHeap :: Heap address value
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
|
||||||
|
type Cacheable term address value = (Ord address, Ord term, Ord value)
|
||||||
|
|
||||||
|
-- | Look up the resulting value & 'Heap' for a given 'Configuration'.
|
||||||
|
cacheLookup :: Cacheable term address value => Configuration term address value -> Cache term address value -> Maybe (Set (Cached address value))
|
||||||
|
cacheLookup key = Monoidal.lookup key . unCache
|
||||||
|
|
||||||
|
-- | Set the resulting value & 'Heap' for a given 'Configuration', overwriting any previous entry.
|
||||||
|
cacheSet :: Cacheable term address value => Configuration term address value -> Set (Cached address value) -> Cache term address value -> Cache term address value
|
||||||
|
cacheSet key value = Cache . Monoidal.insert key value . unCache
|
||||||
|
|
||||||
|
-- | Insert the resulting value & 'Heap' for a given 'Configuration', appending onto any previous entry.
|
||||||
|
cacheInsert :: Cacheable term address value => Configuration term address value -> Cached address value -> Cache term address value -> Cache term address value
|
||||||
|
cacheInsert = curry cons
|
||||||
|
|
||||||
|
instance (Show term, Show address, Show value) => Show (Cache term address value) where
|
||||||
|
showsPrec d = showsUnaryWith showsPrec "Cache" d . map (second toList) . Monoidal.pairs . unCache
|
@ -4,9 +4,9 @@ module Analysis.Abstract.Tracing
|
|||||||
, tracing
|
, tracing
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Abstract.Configuration
|
|
||||||
import Control.Abstract hiding (trace)
|
import Control.Abstract hiding (trace)
|
||||||
import Control.Monad.Effect.Writer
|
import Control.Monad.Effect.Writer
|
||||||
|
import Data.Abstract.Environment
|
||||||
import Data.Semigroup.Reducer as Reducer
|
import Data.Semigroup.Reducer as Reducer
|
||||||
import Prologue
|
import Prologue
|
||||||
|
|
||||||
@ -14,7 +14,6 @@ import Prologue
|
|||||||
--
|
--
|
||||||
-- 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 :: ( Corecursive term
|
tracingTerms :: ( Corecursive term
|
||||||
, Member (Reader (Live address)) effects
|
|
||||||
, Member (Env address) effects
|
, Member (Env address) effects
|
||||||
, Member (State (Heap address value)) effects
|
, Member (State (Heap address value)) effects
|
||||||
, Member (Writer (trace (Configuration term address value))) effects
|
, Member (Writer (trace (Configuration term address value))) effects
|
||||||
@ -30,3 +29,18 @@ trace = tell
|
|||||||
|
|
||||||
tracing :: (Monoid (trace (Configuration term address value)), Effects effects) => TermEvaluator term address value (Writer (trace (Configuration term address value)) ': effects) a -> TermEvaluator term address value effects (trace (Configuration term address value), a)
|
tracing :: (Monoid (trace (Configuration term address value)), Effects effects) => TermEvaluator term address value (Writer (trace (Configuration term address value)) ': effects) a -> TermEvaluator term address value effects (trace (Configuration term address value), a)
|
||||||
tracing = runWriter
|
tracing = runWriter
|
||||||
|
|
||||||
|
|
||||||
|
-- | Get the current 'Configuration' with a passed-in term.
|
||||||
|
getConfiguration :: (Member (Env address) effects, Member (State (Heap address value)) effects)
|
||||||
|
=> term
|
||||||
|
-> TermEvaluator term address value effects (Configuration term address value)
|
||||||
|
getConfiguration term = Configuration term <$> TermEvaluator getEvalContext <*> TermEvaluator getHeap
|
||||||
|
|
||||||
|
-- | A single point in a program’s execution.
|
||||||
|
data Configuration term address value = Configuration
|
||||||
|
{ configurationTerm :: term -- ^ The “instruction,” i.e. the current term to evaluate.
|
||||||
|
, configurationContext :: EvalContext address -- ^ The evaluation context in 'configurationTerm'.
|
||||||
|
, configurationHeap :: Heap address value -- ^ The heap of values.
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
module Control.Abstract.Configuration
|
|
||||||
( getConfiguration
|
|
||||||
) where
|
|
||||||
|
|
||||||
import Control.Abstract.Environment
|
|
||||||
import Control.Abstract.Heap
|
|
||||||
import Control.Abstract.Roots
|
|
||||||
import Control.Abstract.TermEvaluator
|
|
||||||
|
|
||||||
-- | Get the current 'Configuration' with a passed-in term.
|
|
||||||
getConfiguration :: (Member (Reader (Live address)) effects, Member (Env address) effects, Member (State (Heap address value)) effects)
|
|
||||||
=> term
|
|
||||||
-> TermEvaluator term address value effects (Configuration term address value)
|
|
||||||
getConfiguration term = Configuration term <$> TermEvaluator askRoots <*> TermEvaluator getEvalContext <*> TermEvaluator getHeap
|
|
||||||
|
|
@ -8,11 +8,13 @@ module Control.Abstract.Context
|
|||||||
, Span
|
, Span
|
||||||
, currentSpan
|
, currentSpan
|
||||||
, withCurrentSpan
|
, withCurrentSpan
|
||||||
|
, modifyChildSpan
|
||||||
, withCurrentCallStack
|
, withCurrentCallStack
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Effect
|
import Control.Monad.Effect
|
||||||
import Control.Monad.Effect.Reader
|
import Control.Monad.Effect.Reader
|
||||||
|
import Control.Monad.Effect.State
|
||||||
import Data.Abstract.Module
|
import Data.Abstract.Module
|
||||||
import Data.Abstract.Package
|
import Data.Abstract.Package
|
||||||
import Data.Span
|
import Data.Span
|
||||||
@ -43,6 +45,8 @@ currentSpan = ask
|
|||||||
withCurrentSpan :: (Effectful m, Member (Reader Span) effects) => Span -> m effects a -> m effects a
|
withCurrentSpan :: (Effectful m, Member (Reader Span) effects) => Span -> m effects a -> m effects a
|
||||||
withCurrentSpan = local . const
|
withCurrentSpan = local . const
|
||||||
|
|
||||||
|
modifyChildSpan :: (Effectful m, Member (State Span) effects) => Span -> m effects a -> m effects a
|
||||||
|
modifyChildSpan span m = raiseEff (lowerEff m >>= (\a -> modify' (const span) >> pure a))
|
||||||
|
|
||||||
-- | 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'.
|
||||||
withCurrentSrcLoc :: (Effectful m, Member (Reader ModuleInfo) effects, Member (Reader Span) effects) => SrcLoc -> m effects a -> m effects a
|
withCurrentSrcLoc :: (Effectful m, Member (Reader ModuleInfo) effects, Member (Reader Span) effects) => SrcLoc -> m effects a -> m effects a
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{-# LANGUAGE GADTs, KindSignatures, RankNTypes, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE GADTs, KindSignatures, RankNTypes, TypeOperators, UndecidableInstances #-}
|
||||||
module Control.Abstract.Heap
|
module Control.Abstract.Heap
|
||||||
( Heap
|
( Heap
|
||||||
, Configuration(..)
|
|
||||||
, Live
|
, Live
|
||||||
, getHeap
|
, getHeap
|
||||||
, putHeap
|
, putHeap
|
||||||
@ -22,7 +21,6 @@ module Control.Abstract.Heap
|
|||||||
|
|
||||||
import Control.Abstract.Evaluator
|
import Control.Abstract.Evaluator
|
||||||
import Control.Abstract.Roots
|
import Control.Abstract.Roots
|
||||||
import Data.Abstract.Configuration
|
|
||||||
import Data.Abstract.BaseError
|
import Data.Abstract.BaseError
|
||||||
import Data.Abstract.Heap
|
import Data.Abstract.Heap
|
||||||
import Data.Abstract.Live
|
import Data.Abstract.Live
|
||||||
|
@ -30,8 +30,9 @@ import qualified Data.Set as Set
|
|||||||
import Data.Span
|
import Data.Span
|
||||||
import Prologue
|
import Prologue
|
||||||
import System.FilePath.Posix (takeDirectory)
|
import System.FilePath.Posix (takeDirectory)
|
||||||
|
import Data.Abstract.ScopeGraph
|
||||||
|
|
||||||
type ModuleResult address = (Bindings address, address)
|
type ModuleResult address = (ScopeGraph address, (Bindings address, address))
|
||||||
|
|
||||||
-- | Retrieve an evaluated module, if any. @Nothing@ means we’ve never tried to load it, and @Just (env, value)@ indicates the result of a completed load.
|
-- | Retrieve an evaluated module, if any. @Nothing@ means we’ve never tried to load it, and @Just (env, value)@ indicates the result of a completed load.
|
||||||
lookupModule :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Maybe (ModuleResult address))
|
lookupModule :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Maybe (ModuleResult address))
|
||||||
@ -94,7 +95,7 @@ askModuleTable = ask
|
|||||||
newtype Merging address = Merging { runMerging :: ModuleResult address }
|
newtype Merging address = Merging { runMerging :: ModuleResult address }
|
||||||
|
|
||||||
instance Semigroup (Merging address) where
|
instance Semigroup (Merging address) where
|
||||||
Merging (binds1, _) <> Merging (binds2, addr) = Merging (binds1 <> binds2, addr)
|
Merging (_, (binds1, _)) <> Merging (graph2, (binds2, addr)) = Merging (graph2, (binds1 <> binds2, addr))
|
||||||
|
|
||||||
|
|
||||||
-- | An error thrown when loading a module from the list of provided modules. Indicates we weren't able to find a module with the given name.
|
-- | An error thrown when loading a module from the list of provided modules. Indicates we weren't able to find a module with the given name.
|
||||||
|
98
src/Control/Abstract/ScopeGraph.hs
Normal file
98
src/Control/Abstract/ScopeGraph.hs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{-# LANGUAGE GADTs, KindSignatures, LambdaCase, RankNTypes, ScopedTypeVariables, TypeOperators #-}
|
||||||
|
module Control.Abstract.ScopeGraph
|
||||||
|
( runScopeEnv
|
||||||
|
, ScopeEnv
|
||||||
|
, lookup
|
||||||
|
, declare
|
||||||
|
, reference
|
||||||
|
, newScope
|
||||||
|
, Declaration(..)
|
||||||
|
, Reference(..)
|
||||||
|
, EdgeLabel(..)
|
||||||
|
, currentScope
|
||||||
|
, withScope
|
||||||
|
, associatedScope
|
||||||
|
, putDeclarationScope
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Abstract.Evaluator hiding (Local)
|
||||||
|
import Control.Abstract.Heap
|
||||||
|
import Data.Abstract.Name
|
||||||
|
import Data.Abstract.ScopeGraph (Declaration (..), EdgeLabel, Reference, ScopeGraph)
|
||||||
|
import qualified Data.Abstract.ScopeGraph as ScopeGraph
|
||||||
|
import Data.Span
|
||||||
|
import Prelude hiding (lookup)
|
||||||
|
import Prologue
|
||||||
|
|
||||||
|
data ScopeEnv address (m :: * -> *) a where
|
||||||
|
Lookup :: Reference -> ScopeEnv address m (Maybe address)
|
||||||
|
Declare :: Declaration -> Span -> Maybe address -> ScopeEnv address m ()
|
||||||
|
PutDeclarationScope :: Declaration -> address -> ScopeEnv address m ()
|
||||||
|
Reference :: Reference -> Declaration -> ScopeEnv address m ()
|
||||||
|
NewScope :: Map EdgeLabel [address] -> ScopeEnv address m address
|
||||||
|
CurrentScope :: ScopeEnv address m (Maybe address)
|
||||||
|
Local :: address -> m a -> ScopeEnv address m a
|
||||||
|
AssociatedScope :: Declaration -> ScopeEnv address m (Maybe address)
|
||||||
|
|
||||||
|
lookup :: forall address value effects. Member (ScopeEnv address) effects => Reference -> Evaluator address value effects (Maybe address)
|
||||||
|
lookup = send . Lookup @address
|
||||||
|
|
||||||
|
declare :: forall address value effects. Member (ScopeEnv address) effects => Declaration -> Span -> Maybe address -> Evaluator address value effects ()
|
||||||
|
declare = ((send .) .) . Declare @address
|
||||||
|
|
||||||
|
putDeclarationScope :: forall address value effects. Member (ScopeEnv address) effects => Declaration -> address -> Evaluator address value effects ()
|
||||||
|
putDeclarationScope = (send .) . PutDeclarationScope @address
|
||||||
|
|
||||||
|
reference :: forall address value effects. Member (ScopeEnv address) effects => Reference -> Declaration -> Evaluator address value effects ()
|
||||||
|
reference = (send .) . Reference @address
|
||||||
|
|
||||||
|
newScope :: forall address value effects. (Member (ScopeEnv address) effects) => Map EdgeLabel [address] -> Evaluator address value effects address
|
||||||
|
newScope map = send (NewScope map)
|
||||||
|
|
||||||
|
currentScope :: forall address value effects. Member (ScopeEnv address) effects => Evaluator address value effects (Maybe address)
|
||||||
|
currentScope = send CurrentScope
|
||||||
|
|
||||||
|
associatedScope :: forall address value effects. Member (ScopeEnv address) effects => Declaration -> Evaluator address value effects (Maybe address)
|
||||||
|
associatedScope = send . AssociatedScope
|
||||||
|
|
||||||
|
withScope :: forall address value effects m a. (Effectful (m address value), Member (ScopeEnv address) effects) => address -> m address value effects a -> m address value effects a
|
||||||
|
withScope scope action = send (Local scope (lowerEff action))
|
||||||
|
|
||||||
|
instance PureEffect (ScopeEnv address)
|
||||||
|
instance Effect (ScopeEnv address) where
|
||||||
|
handleState c dist (Request (Lookup ref) k) = Request (Lookup ref) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (Declare decl span assocScope) k) = Request (Declare decl span assocScope) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (PutDeclarationScope decl assocScope) k) = Request (PutDeclarationScope decl assocScope) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (Reference ref decl) k) = Request (Reference ref decl) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (NewScope edges) k) = Request (NewScope edges) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request CurrentScope k) = Request CurrentScope (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (AssociatedScope decl) k) = Request (AssociatedScope decl) (dist . (<$ c) . k)
|
||||||
|
handleState c dist (Request (Local scope action) k) = Request (Local scope (dist (action <$ c))) (dist . fmap k)
|
||||||
|
|
||||||
|
|
||||||
|
runScopeEnv :: (Ord address, Effects effects, Member Fresh effects, Member (Allocator address) effects)
|
||||||
|
=> Evaluator address value (ScopeEnv address ': effects) a
|
||||||
|
-> Evaluator address value effects (ScopeGraph address, a)
|
||||||
|
runScopeEnv evaluator = runState lowerBound (reinterpret handleScopeEnv evaluator)
|
||||||
|
|
||||||
|
handleScopeEnv :: forall address value effects a. (Ord address, Member Fresh effects, Member (Allocator address) effects, Effects effects)
|
||||||
|
=> ScopeEnv address (Eff (ScopeEnv address ': effects)) a
|
||||||
|
-> Evaluator address value (State (ScopeGraph address) ': effects) a
|
||||||
|
handleScopeEnv = \case
|
||||||
|
Lookup ref -> ScopeGraph.scopeOfRef ref <$> get
|
||||||
|
Declare decl span scope -> modify @(ScopeGraph address) (ScopeGraph.declare decl span scope)
|
||||||
|
PutDeclarationScope decl scope -> modify @(ScopeGraph address) (ScopeGraph.insertDeclarationScope decl scope)
|
||||||
|
Reference ref decl -> modify @(ScopeGraph address) (ScopeGraph.reference ref decl)
|
||||||
|
NewScope edges -> do
|
||||||
|
-- Take the edges and construct a new scope, update the current scope to the new scope
|
||||||
|
name <- gensym
|
||||||
|
address <- alloc name
|
||||||
|
address <$ modify @(ScopeGraph address) (ScopeGraph.newScope address edges)
|
||||||
|
CurrentScope -> ScopeGraph.currentScope <$> get
|
||||||
|
AssociatedScope decl -> ScopeGraph.associatedScope decl <$> get
|
||||||
|
Local scope action -> do
|
||||||
|
prevScope <- ScopeGraph.currentScope <$> get
|
||||||
|
modify @(ScopeGraph address) (\g -> g { ScopeGraph.currentScope = Just scope })
|
||||||
|
value <- reinterpret handleScopeEnv (raiseEff action)
|
||||||
|
modify @(ScopeGraph address) (\g -> g { ScopeGraph.currentScope = prevScope })
|
||||||
|
pure value
|
@ -1,48 +0,0 @@
|
|||||||
{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, TypeFamilies #-}
|
|
||||||
module Data.Abstract.Cache
|
|
||||||
( Cache
|
|
||||||
, Cached (..)
|
|
||||||
, Cacheable
|
|
||||||
, cacheLookup
|
|
||||||
, cacheSet
|
|
||||||
, cacheInsert
|
|
||||||
, cacheKeys
|
|
||||||
) where
|
|
||||||
|
|
||||||
import Data.Abstract.Configuration
|
|
||||||
import Data.Abstract.Heap
|
|
||||||
import Data.Abstract.Ref
|
|
||||||
import Data.Map.Monoidal as Monoidal
|
|
||||||
import Prologue
|
|
||||||
|
|
||||||
-- | A map of 'Configuration's to 'Set's of resulting values & 'Heap's.
|
|
||||||
newtype Cache term address value = Cache { unCache :: Monoidal.Map (Configuration term address value) (Set (Cached address value)) }
|
|
||||||
deriving (Eq, Lower, Monoid, Ord, Reducer (Configuration term address value, Cached address value), Semigroup)
|
|
||||||
|
|
||||||
data Cached address value = Cached
|
|
||||||
{ cachedValue :: ValueRef address
|
|
||||||
, cachedHeap :: Heap address value
|
|
||||||
}
|
|
||||||
deriving (Eq, Ord, Show)
|
|
||||||
|
|
||||||
|
|
||||||
type Cacheable term address value = (Ord address, Ord term, Ord value)
|
|
||||||
|
|
||||||
-- | Look up the resulting value & 'Heap' for a given 'Configuration'.
|
|
||||||
cacheLookup :: Cacheable term address value => Configuration term address value -> Cache term address value -> Maybe (Set (Cached address value))
|
|
||||||
cacheLookup key = Monoidal.lookup key . unCache
|
|
||||||
|
|
||||||
-- | Set the resulting value & 'Heap' for a given 'Configuration', overwriting any previous entry.
|
|
||||||
cacheSet :: Cacheable term address value => Configuration term address value -> Set (Cached address value) -> Cache term address value -> Cache term address value
|
|
||||||
cacheSet key value = Cache . Monoidal.insert key value . unCache
|
|
||||||
|
|
||||||
-- | Insert the resulting value & 'Heap' for a given 'Configuration', appending onto any previous entry.
|
|
||||||
cacheInsert :: Cacheable term address value => Configuration term address value -> Cached address value -> Cache term address value -> Cache term address value
|
|
||||||
cacheInsert = curry cons
|
|
||||||
|
|
||||||
-- | Return all 'Configuration's in the provided cache.
|
|
||||||
cacheKeys :: Cache term address value -> [Configuration term address value]
|
|
||||||
cacheKeys = Monoidal.keys . unCache
|
|
||||||
|
|
||||||
instance (Show term, Show address, Show value) => Show (Cache term address value) where
|
|
||||||
showsPrec d = showsUnaryWith showsPrec "Cache" d . map (second toList) . Monoidal.pairs . unCache
|
|
@ -1,14 +0,0 @@
|
|||||||
module Data.Abstract.Configuration ( Configuration (..) ) where
|
|
||||||
|
|
||||||
import Data.Abstract.Environment
|
|
||||||
import Data.Abstract.Heap
|
|
||||||
import Data.Abstract.Live
|
|
||||||
|
|
||||||
-- | A single point in a program’s execution.
|
|
||||||
data Configuration term address value = Configuration
|
|
||||||
{ configurationTerm :: term -- ^ The “instruction,” i.e. the current term to evaluate.
|
|
||||||
, configurationRoots :: Live address -- ^ The set of rooted addresses.
|
|
||||||
, configurationContext :: EvalContext address -- ^ The evaluation context in 'configurationTerm'.
|
|
||||||
, configurationHeap :: Heap address value -- ^ The heap of values.
|
|
||||||
}
|
|
||||||
deriving (Eq, Ord, Show)
|
|
@ -28,6 +28,7 @@ import Control.Abstract.Evaluator as X hiding (LoopControl(..), Return(..), catc
|
|||||||
import Control.Abstract.Heap as X hiding (runAddressError, runAddressErrorWith)
|
import Control.Abstract.Heap as X hiding (runAddressError, runAddressErrorWith)
|
||||||
import Control.Abstract.Modules as X (Modules, ModuleResult, ResolutionError(..), load, lookupModule, listModulesInDir, require, resolve, throwResolutionError)
|
import Control.Abstract.Modules as X (Modules, ModuleResult, ResolutionError(..), load, lookupModule, listModulesInDir, require, resolve, throwResolutionError)
|
||||||
import Control.Abstract.Value as X hiding (Boolean(..), Function(..))
|
import Control.Abstract.Value as X hiding (Boolean(..), Function(..))
|
||||||
|
import Control.Abstract.ScopeGraph
|
||||||
import Data.Abstract.Declarations as X
|
import Data.Abstract.Declarations as X
|
||||||
import Data.Abstract.Environment as X
|
import Data.Abstract.Environment as X
|
||||||
import Data.Abstract.BaseError as X
|
import Data.Abstract.BaseError as X
|
||||||
@ -53,6 +54,7 @@ class (Show1 constr, Foldable constr) => Evaluatable constr where
|
|||||||
, Member (Allocator address) effects
|
, Member (Allocator address) effects
|
||||||
, Member (Boolean value) effects
|
, Member (Boolean value) effects
|
||||||
, Member (Deref value) effects
|
, Member (Deref value) effects
|
||||||
|
, Member (ScopeEnv address) effects
|
||||||
, Member (Env address) effects
|
, Member (Env address) effects
|
||||||
, Member (Exc (LoopControl address)) effects
|
, Member (Exc (LoopControl address)) effects
|
||||||
, Member (Exc (Return address)) effects
|
, Member (Exc (Return address)) effects
|
||||||
@ -62,6 +64,7 @@ class (Show1 constr, Foldable constr) => Evaluatable constr where
|
|||||||
, Member (Reader ModuleInfo) effects
|
, Member (Reader ModuleInfo) effects
|
||||||
, Member (Reader PackageInfo) effects
|
, Member (Reader PackageInfo) effects
|
||||||
, Member (Reader Span) effects
|
, Member (Reader Span) effects
|
||||||
|
, Member (State Span) effects
|
||||||
, Member (Resumable (BaseError (AddressError address value))) effects
|
, Member (Resumable (BaseError (AddressError address value))) effects
|
||||||
, Member (Resumable (BaseError (EnvironmentError address))) effects
|
, Member (Resumable (BaseError (EnvironmentError address))) effects
|
||||||
, Member (Resumable (BaseError (UnspecializedError value))) effects
|
, Member (Resumable (BaseError (UnspecializedError value))) effects
|
||||||
@ -82,6 +85,7 @@ type ModuleEffects address value rest
|
|||||||
= Exc (LoopControl address)
|
= Exc (LoopControl address)
|
||||||
': Exc (Return address)
|
': Exc (Return address)
|
||||||
': Env address
|
': Env address
|
||||||
|
': ScopeEnv address
|
||||||
': Deref value
|
': Deref value
|
||||||
': Allocator address
|
': Allocator address
|
||||||
': Reader ModuleInfo
|
': Reader ModuleInfo
|
||||||
@ -104,6 +108,7 @@ evaluate :: ( AbstractValue address value valueEffects
|
|||||||
, Member (Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))) effects
|
, Member (Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))) effects
|
||||||
, Member (Reader PackageInfo) effects
|
, Member (Reader PackageInfo) effects
|
||||||
, Member (Reader Span) effects
|
, Member (Reader Span) effects
|
||||||
|
, Member (State Span) effects
|
||||||
, Member (Resumable (BaseError (AddressError address value))) effects
|
, Member (Resumable (BaseError (AddressError address value))) effects
|
||||||
, Member (Resumable (BaseError (EnvironmentError address))) effects
|
, Member (Resumable (BaseError (EnvironmentError address))) effects
|
||||||
, Member (Resumable (BaseError EvalError)) effects
|
, Member (Resumable (BaseError EvalError)) effects
|
||||||
@ -124,7 +129,7 @@ evaluate :: ( AbstractValue address value valueEffects
|
|||||||
-> [Module term]
|
-> [Module term]
|
||||||
-> TermEvaluator term address value effects (ModuleTable (NonEmpty (Module (ModuleResult address))))
|
-> TermEvaluator term address value effects (ModuleTable (NonEmpty (Module (ModuleResult address))))
|
||||||
evaluate lang analyzeModule analyzeTerm runAllocDeref runValue modules = do
|
evaluate lang analyzeModule analyzeTerm runAllocDeref runValue modules = do
|
||||||
(preludeBinds, _) <- TermEvaluator . runInModule lowerBound moduleInfoFromCallStack . runValue $ do
|
(_, (preludeBinds, _)) <- TermEvaluator . runInModule lowerBound moduleInfoFromCallStack . runValue $ do
|
||||||
definePrelude lang
|
definePrelude lang
|
||||||
box unit
|
box unit
|
||||||
foldr (run preludeBinds) ask modules
|
foldr (run preludeBinds) ask modules
|
||||||
@ -143,6 +148,7 @@ evaluate lang analyzeModule analyzeTerm runAllocDeref runValue modules = do
|
|||||||
runInModule preludeBinds info
|
runInModule preludeBinds info
|
||||||
= runReader info
|
= runReader info
|
||||||
. runAllocDeref
|
. runAllocDeref
|
||||||
|
. runScopeEnv
|
||||||
. runEnv (EvalContext Nothing (X.push (newEnv preludeBinds)))
|
. runEnv (EvalContext Nothing (X.push (newEnv preludeBinds)))
|
||||||
. runReturn
|
. runReturn
|
||||||
. runLoopControl
|
. runLoopControl
|
||||||
|
242
src/Data/Abstract/ScopeGraph.hs
Normal file
242
src/Data/Abstract/ScopeGraph.hs
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
{-# LANGUAGE GADTs #-}
|
||||||
|
module Data.Abstract.ScopeGraph
|
||||||
|
( ScopeGraph(..)
|
||||||
|
, Path
|
||||||
|
, pathDeclaration
|
||||||
|
, Reference(..)
|
||||||
|
, Declaration(..)
|
||||||
|
, EdgeLabel(..)
|
||||||
|
, Frame
|
||||||
|
, Heap
|
||||||
|
, frameLookup
|
||||||
|
, scopeLookup
|
||||||
|
, frameSlots
|
||||||
|
, frameLinks
|
||||||
|
, getSlot
|
||||||
|
, setSlot
|
||||||
|
, lookup
|
||||||
|
, scopeOfRef
|
||||||
|
, pathOfRef
|
||||||
|
, declare
|
||||||
|
, reference
|
||||||
|
, newScope
|
||||||
|
, associatedScope
|
||||||
|
, insertDeclarationScope
|
||||||
|
, newFrame
|
||||||
|
, initFrame
|
||||||
|
, insertFrame
|
||||||
|
, fillFrame
|
||||||
|
, deleteFrame
|
||||||
|
, heapSize
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Abstract.Name
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Data.Span
|
||||||
|
import Prelude hiding (lookup)
|
||||||
|
import Prologue
|
||||||
|
|
||||||
|
data Scope scopeAddress = Scope {
|
||||||
|
edges :: Map EdgeLabel [scopeAddress] -- Maybe Map EdgeLabel [Path scope]?
|
||||||
|
, references :: Map Reference (Path scopeAddress)
|
||||||
|
, declarations :: Map Declaration (Span, Maybe scopeAddress)
|
||||||
|
} deriving (Eq, Show, Ord)
|
||||||
|
|
||||||
|
|
||||||
|
data ScopeGraph scope = ScopeGraph { graph :: Map scope (Scope scope), currentScope :: Maybe scope }
|
||||||
|
|
||||||
|
instance Ord scope => Lower (ScopeGraph scope) where
|
||||||
|
lowerBound = ScopeGraph mempty Nothing
|
||||||
|
|
||||||
|
deriving instance Eq address => Eq (ScopeGraph address)
|
||||||
|
deriving instance Show address => Show (ScopeGraph address)
|
||||||
|
deriving instance Ord address => Ord (ScopeGraph address)
|
||||||
|
|
||||||
|
data Path scope where
|
||||||
|
-- | Construct a direct path to a declaration.
|
||||||
|
DPath :: Declaration -> Path scope
|
||||||
|
-- | Construct an edge from a scope to another declaration path.
|
||||||
|
EPath :: EdgeLabel -> scope -> Path scope -> Path scope
|
||||||
|
|
||||||
|
deriving instance Eq scope => Eq (Path scope)
|
||||||
|
deriving instance Show scope => Show (Path scope)
|
||||||
|
deriving instance Ord scope => Ord (Path scope)
|
||||||
|
|
||||||
|
-- Returns the declaration of a path.
|
||||||
|
pathDeclaration :: Path scope -> Declaration
|
||||||
|
pathDeclaration (DPath d) = d
|
||||||
|
pathDeclaration (EPath _ _ p) = pathDeclaration p
|
||||||
|
|
||||||
|
-- Returns the reference paths of a scope in a scope graph.
|
||||||
|
pathsOfScope :: Ord scope => scope -> ScopeGraph scope -> Maybe (Map Reference (Path scope))
|
||||||
|
pathsOfScope scope = fmap references . Map.lookup scope . graph
|
||||||
|
|
||||||
|
-- Returns the declaration data of a scope in a scope graph.
|
||||||
|
ddataOfScope :: Ord scope => scope -> ScopeGraph scope -> Maybe (Map Declaration (Span, Maybe scope))
|
||||||
|
ddataOfScope scope = fmap declarations . Map.lookup scope . graph
|
||||||
|
|
||||||
|
-- Returns the edges of a scope in a scope graph.
|
||||||
|
linksOfScope :: Ord scope => scope -> ScopeGraph scope -> Maybe (Map EdgeLabel [scope])
|
||||||
|
linksOfScope scope = fmap edges . Map.lookup scope . graph
|
||||||
|
|
||||||
|
-- Lookup a scope in the scope graph.
|
||||||
|
lookupScope :: Ord scope => scope -> ScopeGraph scope -> Maybe (Scope scope)
|
||||||
|
lookupScope scope = Map.lookup scope . graph
|
||||||
|
|
||||||
|
-- Declare a declaration with a span and an associated scope in the scope graph.
|
||||||
|
declare :: Ord scope => Declaration -> Span -> Maybe scope -> ScopeGraph scope -> ScopeGraph scope
|
||||||
|
declare declaration ddata assocScope g@ScopeGraph{..} = fromMaybe g $ do
|
||||||
|
scopeKey <- currentScope
|
||||||
|
scope <- lookupScope scopeKey g
|
||||||
|
let newScope = scope { declarations = Map.insert declaration (ddata, assocScope) (declarations scope) }
|
||||||
|
pure $ g { graph = Map.insert scopeKey newScope graph }
|
||||||
|
|
||||||
|
-- | Add a reference to a declaration in the scope graph.
|
||||||
|
-- Returns the original scope graph if the declaration could not be found.
|
||||||
|
reference :: Ord scope => Reference -> Declaration -> ScopeGraph scope -> ScopeGraph scope
|
||||||
|
reference ref declaration g@ScopeGraph{..} = fromMaybe g $ do
|
||||||
|
currentAddress <- currentScope
|
||||||
|
currentScope' <- lookupScope currentAddress g
|
||||||
|
go currentAddress currentScope' currentAddress id
|
||||||
|
where
|
||||||
|
declDataOfScope address = do
|
||||||
|
dataMap <- ddataOfScope address g
|
||||||
|
Map.lookup declaration dataMap
|
||||||
|
go currentAddress currentScope address path =
|
||||||
|
case declDataOfScope address of
|
||||||
|
Just _ ->
|
||||||
|
let newScope = currentScope { references = Map.insert ref (path (DPath declaration)) (references currentScope) }
|
||||||
|
in Just (g { graph = Map.insert currentAddress newScope graph })
|
||||||
|
Nothing -> let
|
||||||
|
traverseEdges edge = do
|
||||||
|
linkMap <- linksOfScope address g
|
||||||
|
scopes <- Map.lookup edge linkMap
|
||||||
|
-- Return the first path to the declaration through the scopes.
|
||||||
|
getFirst (foldMap (First . ap (go currentAddress currentScope) ((path .) . EPath edge)) scopes)
|
||||||
|
in traverseEdges Import <|> traverseEdges Lexical
|
||||||
|
|
||||||
|
-- | Insert associate the given address to a declaration in the scope graph.
|
||||||
|
insertDeclarationScope :: Ord address => Declaration -> address -> ScopeGraph address -> ScopeGraph address
|
||||||
|
insertDeclarationScope decl address g@ScopeGraph{..} = fromMaybe g $ do
|
||||||
|
declScope <- scopeOfDeclaration decl g
|
||||||
|
scope <- lookupScope declScope g
|
||||||
|
(span, _) <- Map.lookup decl (declarations scope)
|
||||||
|
pure $ g { graph = Map.insert declScope (scope { declarations = Map.insert decl (span, Just address) (declarations scope) }) graph }
|
||||||
|
|
||||||
|
-- | Insert a new scope with the given address and edges into the scope graph.
|
||||||
|
newScope :: Ord address => address -> Map EdgeLabel [address] -> ScopeGraph address -> ScopeGraph address
|
||||||
|
newScope address edges g@ScopeGraph{..} = g { graph = Map.insert address newScope graph }
|
||||||
|
where
|
||||||
|
newScope = Scope edges mempty mempty
|
||||||
|
|
||||||
|
-- | Returns the scope of a reference in the scope graph.
|
||||||
|
scopeOfRef :: Ord scope => Reference -> ScopeGraph scope -> Maybe scope
|
||||||
|
scopeOfRef ref g@ScopeGraph{..} = go (Map.keys graph)
|
||||||
|
where
|
||||||
|
go (s : scopes') = fromMaybe (go scopes') $ do
|
||||||
|
pathMap <- pathsOfScope s g
|
||||||
|
_ <- Map.lookup ref pathMap
|
||||||
|
pure (Just s)
|
||||||
|
go [] = Nothing
|
||||||
|
|
||||||
|
-- | Returns the path of a reference in the scope graph.
|
||||||
|
pathOfRef :: (Ord scope) => Reference -> ScopeGraph scope -> Maybe (Path scope)
|
||||||
|
pathOfRef ref graph = do
|
||||||
|
scope <- scopeOfRef ref graph
|
||||||
|
pathsMap <- pathsOfScope scope graph
|
||||||
|
Map.lookup ref pathsMap
|
||||||
|
|
||||||
|
-- Returns the scope the declaration was declared in.
|
||||||
|
scopeOfDeclaration :: Ord scope => Declaration -> ScopeGraph scope -> Maybe scope
|
||||||
|
scopeOfDeclaration declaration g@ScopeGraph{..} = go (Map.keys graph)
|
||||||
|
where
|
||||||
|
go (s : scopes') = fromMaybe (go scopes') $ do
|
||||||
|
ddataMap <- ddataOfScope s g
|
||||||
|
_ <- Map.lookup declaration ddataMap
|
||||||
|
pure (Just s)
|
||||||
|
go [] = Nothing
|
||||||
|
|
||||||
|
-- | Returns the scope associated with a declaration (the child scope if any exists).
|
||||||
|
associatedScope :: Ord scope => Declaration -> ScopeGraph scope -> Maybe scope
|
||||||
|
associatedScope declaration g@ScopeGraph{..} = go (Map.keys graph)
|
||||||
|
where
|
||||||
|
go (s : scopes') = fromMaybe (go scopes') $ do
|
||||||
|
ddataMap <- ddataOfScope s g
|
||||||
|
(_, assocScope) <- Map.lookup declaration ddataMap
|
||||||
|
pure assocScope
|
||||||
|
go [] = Nothing
|
||||||
|
|
||||||
|
newtype Reference = Reference Name
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
newtype Declaration = Declaration Name
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
-- | The type of edge from a scope to its parent scopes.
|
||||||
|
-- Either a lexical edge or an import edge in the case of non-lexical edges.
|
||||||
|
data EdgeLabel = Lexical | Import
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
data Frame scopeAddress frameAddress value = Frame {
|
||||||
|
scopeAddress :: scopeAddress
|
||||||
|
, links :: Map EdgeLabel (Map scopeAddress frameAddress)
|
||||||
|
, slots :: Map Declaration value
|
||||||
|
}
|
||||||
|
|
||||||
|
newtype Heap scopeAddress frameAddress value = Heap { unHeap :: Map frameAddress (Frame scopeAddress frameAddress value) }
|
||||||
|
|
||||||
|
-- | Look up the frame for an 'address' in a 'Heap', if any.
|
||||||
|
frameLookup :: Ord address => address -> Heap scope address value -> Maybe (Frame scope address value)
|
||||||
|
frameLookup address = Map.lookup address . unHeap
|
||||||
|
|
||||||
|
-- | Look up the scope address for a given frame address.
|
||||||
|
scopeLookup :: Ord address => address -> Heap scope address value -> Maybe scope
|
||||||
|
scopeLookup address = fmap scopeAddress . frameLookup address
|
||||||
|
|
||||||
|
frameSlots :: Ord address => address -> Heap scope address value -> Maybe (Map Declaration value)
|
||||||
|
frameSlots address = fmap slots . frameLookup address
|
||||||
|
|
||||||
|
frameLinks :: Ord address => address -> Heap scope address value -> Maybe (Map EdgeLabel (Map scope address))
|
||||||
|
frameLinks address = fmap links . frameLookup address
|
||||||
|
|
||||||
|
getSlot :: Ord address => address -> Heap scope address value -> Declaration -> Maybe value
|
||||||
|
getSlot address heap declaration = do
|
||||||
|
slotMap <- frameSlots address heap
|
||||||
|
Map.lookup declaration slotMap
|
||||||
|
|
||||||
|
setSlot :: Ord address => address -> Declaration -> value -> Heap scope address value -> Heap scope address value
|
||||||
|
setSlot address declaration value heap =
|
||||||
|
case frameLookup address heap of
|
||||||
|
Just frame -> let slotMap = slots frame in
|
||||||
|
Heap $ Map.insert address (frame { slots = Map.insert declaration value slotMap }) (unHeap heap)
|
||||||
|
Nothing -> heap
|
||||||
|
|
||||||
|
lookup :: (Ord address, Ord scope) => Heap scope address value -> address -> Path scope -> Declaration -> Maybe scope
|
||||||
|
lookup heap address (DPath d) declaration = guard (d == declaration) >> scopeLookup address heap
|
||||||
|
lookup heap address (EPath label scope path) declaration = do
|
||||||
|
frame <- frameLookup address heap
|
||||||
|
scopeMap <- Map.lookup label (links frame)
|
||||||
|
nextAddress <- Map.lookup scope scopeMap
|
||||||
|
lookup heap nextAddress path declaration
|
||||||
|
|
||||||
|
newFrame :: (Ord address) => scope -> address -> Map EdgeLabel (Map scope address) -> Heap scope address value -> Heap scope address value
|
||||||
|
newFrame scope address links = insertFrame address (Frame scope links mempty)
|
||||||
|
|
||||||
|
initFrame :: (Ord address) => scope -> address -> Map EdgeLabel (Map scope address) -> Map Declaration value -> Heap scope address value -> Heap scope address value
|
||||||
|
initFrame scope address links slots = fillFrame address slots . newFrame scope address links
|
||||||
|
|
||||||
|
insertFrame :: Ord address => address -> Frame scope address value -> Heap scope address value -> Heap scope address value
|
||||||
|
insertFrame address frame = Heap . Map.insert address frame . unHeap
|
||||||
|
|
||||||
|
fillFrame :: Ord address => address -> Map Declaration value -> Heap scope address value -> Heap scope address value
|
||||||
|
fillFrame address slots heap =
|
||||||
|
case frameLookup address heap of
|
||||||
|
Just frame -> insertFrame address (frame { slots = slots }) heap
|
||||||
|
Nothing -> heap
|
||||||
|
|
||||||
|
deleteFrame :: Ord address => address -> Heap scope address value -> Heap scope address value
|
||||||
|
deleteFrame address = Heap . Map.delete address . unHeap
|
||||||
|
|
||||||
|
-- | The number of frames in the `Heap`.
|
||||||
|
heapSize :: Heap scope address value -> Int
|
||||||
|
heapSize = Map.size . unHeap
|
@ -1,14 +1,16 @@
|
|||||||
{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses, ScopedTypeVariables, UndecidableInstances #-}
|
{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses, ScopedTypeVariables, UndecidableInstances, TupleSections #-}
|
||||||
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
|
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
|
||||||
module Data.Syntax.Declaration where
|
module Data.Syntax.Declaration where
|
||||||
|
|
||||||
import qualified Data.Abstract.Environment as Env
|
import qualified Data.Abstract.Environment as Env
|
||||||
import Data.Abstract.Evaluatable
|
import Data.Abstract.Evaluatable
|
||||||
|
import Control.Abstract.ScopeGraph
|
||||||
import Data.JSON.Fields
|
import Data.JSON.Fields
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Diffing.Algorithm
|
import Diffing.Algorithm
|
||||||
import Prologue
|
import Prologue
|
||||||
import Proto3.Suite.Class
|
import Proto3.Suite.Class
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import Reprinting.Tokenize
|
import Reprinting.Tokenize
|
||||||
|
|
||||||
data Function a = Function { functionContext :: ![a], functionName :: !a, functionParameters :: ![a], functionBody :: !a }
|
data Function a = Function { functionContext :: ![a], functionName :: !a, functionParameters :: ![a], functionBody :: !a }
|
||||||
@ -125,7 +127,18 @@ instance Show1 VariableDeclaration where liftShowsPrec = genericLiftShowsPrec
|
|||||||
|
|
||||||
instance Evaluatable VariableDeclaration where
|
instance Evaluatable VariableDeclaration where
|
||||||
eval (VariableDeclaration []) = rvalBox unit
|
eval (VariableDeclaration []) = rvalBox unit
|
||||||
eval (VariableDeclaration decs) = rvalBox =<< tuple =<< traverse subtermAddress decs
|
eval (VariableDeclaration decs) = do
|
||||||
|
addresses <- for decs $ \declaration -> do
|
||||||
|
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm declaration))
|
||||||
|
(span, valueRef) <- do
|
||||||
|
ref <- subtermRef declaration
|
||||||
|
subtermSpan <- get @Span
|
||||||
|
pure (subtermSpan, ref)
|
||||||
|
|
||||||
|
declare (Declaration name) span Nothing -- TODO is it true that variable declarations never have an associated scope?
|
||||||
|
|
||||||
|
address valueRef
|
||||||
|
rvalBox =<< tuple addresses
|
||||||
|
|
||||||
instance Declarations a => Declarations (VariableDeclaration a) where
|
instance Declarations a => Declarations (VariableDeclaration a) where
|
||||||
declaredName (VariableDeclaration vars) = case vars of
|
declaredName (VariableDeclaration vars) = case vars of
|
||||||
@ -158,7 +171,13 @@ instance Ord1 PublicFieldDefinition where liftCompare = genericLiftCompare
|
|||||||
instance Show1 PublicFieldDefinition where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 PublicFieldDefinition where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- TODO: Implement Eval instance for PublicFieldDefinition
|
-- TODO: Implement Eval instance for PublicFieldDefinition
|
||||||
instance Evaluatable PublicFieldDefinition
|
instance Evaluatable PublicFieldDefinition where
|
||||||
|
eval PublicFieldDefinition{..} = do
|
||||||
|
span <- ask @Span
|
||||||
|
propertyName <- maybeM (throwEvalError NoNameError) (declaredName (subterm publicFieldPropertyName))
|
||||||
|
declare (Declaration propertyName) span Nothing
|
||||||
|
rvalBox unit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data Variable a = Variable { variableName :: !a, variableType :: !a, variableValue :: !a }
|
data Variable a = Variable { variableName :: !a, variableType :: !a, variableValue :: !a }
|
||||||
@ -187,13 +206,30 @@ instance Show1 Class where liftShowsPrec = genericLiftShowsPrec
|
|||||||
instance Evaluatable Class where
|
instance Evaluatable Class where
|
||||||
eval Class{..} = do
|
eval Class{..} = do
|
||||||
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm classIdentifier))
|
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm classIdentifier))
|
||||||
supers <- traverse subtermAddress classSuperclasses
|
span <- ask @Span
|
||||||
(_, addr) <- letrec name $ do
|
-- Run the action within the class's scope.
|
||||||
void $ subtermValue classBody
|
currentScope' <- currentScope
|
||||||
classBinds <- Env.head <$> getEnv
|
|
||||||
klass name supers classBinds
|
supers <- for classSuperclasses $ \superclass -> do
|
||||||
bind name addr
|
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm superclass))
|
||||||
pure (Rval addr)
|
scope <- associatedScope (Declaration name)
|
||||||
|
(scope,) <$> subtermAddress superclass
|
||||||
|
|
||||||
|
let imports = (Import,) <$> (fmap pure . catMaybes $ fst <$> supers)
|
||||||
|
current = maybe mempty (fmap (Lexical, ) . pure . pure) currentScope'
|
||||||
|
edges = Map.fromList (imports <> current)
|
||||||
|
childScope <- newScope edges
|
||||||
|
declare (Declaration name) span (Just childScope)
|
||||||
|
|
||||||
|
withScope childScope $ do
|
||||||
|
(_, addr) <- letrec name $ do
|
||||||
|
void $ subtermValue classBody
|
||||||
|
classBinds <- Env.head <$> getEnv
|
||||||
|
klass name (snd <$> supers) classBinds
|
||||||
|
bind name addr
|
||||||
|
pure (Rval addr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- | A decorator in Python
|
-- | A decorator in Python
|
||||||
data Decorator a = Decorator { decoratorIdentifier :: !a, decoratorParamaters :: ![a], decoratorBody :: !a }
|
data Decorator a = Decorator { decoratorIdentifier :: !a, decoratorParamaters :: ![a], decoratorBody :: !a }
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
|
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
|
||||||
module Data.Syntax.Expression where
|
module Data.Syntax.Expression where
|
||||||
|
|
||||||
|
import Control.Abstract.ScopeGraph as ScopeGraph
|
||||||
import Data.Abstract.Evaluatable hiding (Member)
|
import Data.Abstract.Evaluatable hiding (Member)
|
||||||
import Data.Abstract.Number (liftIntegralFrac, liftReal, liftedExponent, liftedFloorDiv)
|
import Data.Abstract.Number (liftIntegralFrac, liftReal, liftedExponent, liftedFloorDiv)
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
@ -424,7 +425,10 @@ instance Evaluatable Complement where
|
|||||||
|
|
||||||
-- | Member Access (e.g. a.b)
|
-- | Member Access (e.g. a.b)
|
||||||
data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name }
|
data MemberAccess a = MemberAccess { lhs :: a, rhs :: Name }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
||||||
|
|
||||||
|
instance Declarations1 MemberAccess where
|
||||||
|
liftDeclaredName _ MemberAccess{..} = Just rhs
|
||||||
|
|
||||||
instance Eq1 MemberAccess where liftEq = genericLiftEq
|
instance Eq1 MemberAccess where liftEq = genericLiftEq
|
||||||
instance Ord1 MemberAccess where liftCompare = genericLiftCompare
|
instance Ord1 MemberAccess where liftCompare = genericLiftCompare
|
||||||
@ -432,7 +436,17 @@ instance Show1 MemberAccess where liftShowsPrec = genericLiftShowsPrec
|
|||||||
|
|
||||||
instance Evaluatable MemberAccess where
|
instance Evaluatable MemberAccess where
|
||||||
eval (MemberAccess obj propName) = do
|
eval (MemberAccess obj propName) = do
|
||||||
|
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm obj))
|
||||||
|
reference (Reference name) (Declaration name)
|
||||||
|
childScope <- associatedScope (Declaration name)
|
||||||
|
|
||||||
ptr <- subtermAddress obj
|
ptr <- subtermAddress obj
|
||||||
|
case childScope of
|
||||||
|
Just childScope -> withScope childScope $ reference (Reference propName) (Declaration propName)
|
||||||
|
Nothing ->
|
||||||
|
-- TODO: Throw an ReferenceError because we can't find the associated child scope for `obj`.
|
||||||
|
pure ()
|
||||||
|
|
||||||
pure $! LvalMember ptr propName
|
pure $! LvalMember ptr propName
|
||||||
|
|
||||||
-- | Subscript (e.g a[1])
|
-- | Subscript (e.g a[1])
|
||||||
@ -523,14 +537,26 @@ instance Evaluatable Await where
|
|||||||
|
|
||||||
-- | An object constructor call in Javascript, Java, etc.
|
-- | An object constructor call in Javascript, Java, etc.
|
||||||
newtype New a = New { newSubject :: [a] }
|
newtype New a = New { newSubject :: [a] }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
||||||
|
|
||||||
|
instance Declarations1 New where
|
||||||
|
liftDeclaredName _ (New []) = Nothing
|
||||||
|
liftDeclaredName declaredName (New (subject : _)) = declaredName subject
|
||||||
|
|
||||||
instance Eq1 New where liftEq = genericLiftEq
|
instance Eq1 New where liftEq = genericLiftEq
|
||||||
instance Ord1 New where liftCompare = genericLiftCompare
|
instance Ord1 New where liftCompare = genericLiftCompare
|
||||||
instance Show1 New where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 New where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- TODO: Implement Eval instance for New
|
-- TODO: Implement Eval instance for New
|
||||||
instance Evaluatable New
|
instance Evaluatable New where
|
||||||
|
eval New{..} = do
|
||||||
|
case newSubject of
|
||||||
|
[] -> pure ()
|
||||||
|
(subject : _) -> do
|
||||||
|
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm subject))
|
||||||
|
reference (Reference name) (Declaration name)
|
||||||
|
-- TODO: Traverse subterms and instantiate frames from the corresponding scope
|
||||||
|
rvalBox unit
|
||||||
|
|
||||||
-- | A cast expression to a specified type.
|
-- | A cast expression to a specified type.
|
||||||
data Cast a = Cast { castSubject :: !a, castType :: !a }
|
data Cast a = Cast { castSubject :: !a, castType :: !a }
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
module Data.Syntax.Statement where
|
module Data.Syntax.Statement where
|
||||||
|
|
||||||
import Data.Abstract.Evaluatable
|
import Data.Abstract.Evaluatable
|
||||||
|
import Control.Abstract.ScopeGraph
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import Data.Aeson (ToJSON1 (..))
|
import Data.Aeson (ToJSON1 (..))
|
||||||
import Data.JSON.Fields
|
import Data.JSON.Fields
|
||||||
import Data.Semigroup.App
|
import Data.Semigroup.App
|
||||||
@ -27,7 +29,11 @@ instance Show1 Statements where liftShowsPrec = genericLiftShowsPrec
|
|||||||
instance ToJSON1 Statements
|
instance ToJSON1 Statements
|
||||||
|
|
||||||
instance Evaluatable Statements where
|
instance Evaluatable Statements where
|
||||||
eval (Statements xs) = maybe (rvalBox unit) (runApp . foldMap1 (App . subtermRef)) (nonEmpty xs)
|
eval (Statements xs) = do
|
||||||
|
currentScope' <- currentScope
|
||||||
|
let edges = maybe mempty (Map.singleton Lexical . pure) currentScope'
|
||||||
|
scope <- newScope edges
|
||||||
|
withScope scope $ maybe (rvalBox unit) (runApp . foldMap1 (App . subtermRef)) (nonEmpty xs)
|
||||||
|
|
||||||
instance Tokenize Statements where
|
instance Tokenize Statements where
|
||||||
tokenize = imperative
|
tokenize = imperative
|
||||||
@ -121,7 +127,10 @@ instance Evaluatable Let where
|
|||||||
|
|
||||||
-- | Assignment to a variable or other lvalue.
|
-- | Assignment to a variable or other lvalue.
|
||||||
data Assignment a = Assignment { assignmentContext :: ![a], assignmentTarget :: !a, assignmentValue :: !a }
|
data Assignment a = Assignment { assignmentContext :: ![a], assignmentTarget :: !a, assignmentValue :: !a }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
|
||||||
|
|
||||||
|
instance Declarations1 Assignment where
|
||||||
|
liftDeclaredName declaredName Assignment{..} = declaredName assignmentTarget
|
||||||
|
|
||||||
instance Eq1 Assignment where liftEq = genericLiftEq
|
instance Eq1 Assignment where liftEq = genericLiftEq
|
||||||
instance Ord1 Assignment where liftCompare = genericLiftCompare
|
instance Ord1 Assignment where liftCompare = genericLiftCompare
|
||||||
@ -133,8 +142,19 @@ instance Evaluatable Assignment where
|
|||||||
rhs <- subtermAddress assignmentValue
|
rhs <- subtermAddress assignmentValue
|
||||||
|
|
||||||
case lhs of
|
case lhs of
|
||||||
LvalLocal nam -> do
|
LvalLocal name -> do
|
||||||
bind nam rhs
|
case declaredName (subterm assignmentValue) of
|
||||||
|
Just rhsName -> do
|
||||||
|
assocScope <- associatedScope (Declaration rhsName)
|
||||||
|
case assocScope of
|
||||||
|
Just assocScope' -> do
|
||||||
|
objectScope <- newScope (Map.singleton Import [ assocScope' ])
|
||||||
|
putDeclarationScope (Declaration name) objectScope
|
||||||
|
Nothing -> pure ()
|
||||||
|
Nothing ->
|
||||||
|
-- The rhs wasn't assigned to a reference/declaration.
|
||||||
|
pure ()
|
||||||
|
bind name rhs
|
||||||
LvalMember _ _ ->
|
LvalMember _ _ ->
|
||||||
-- we don't yet support mutable object properties:
|
-- we don't yet support mutable object properties:
|
||||||
pure ()
|
pure ()
|
||||||
|
@ -267,10 +267,10 @@ floatLiteral :: Assignment Term
|
|||||||
floatLiteral = makeTerm <$> symbol FloatLiteral <*> (Literal.Float <$> source)
|
floatLiteral = makeTerm <$> symbol FloatLiteral <*> (Literal.Float <$> source)
|
||||||
|
|
||||||
identifier :: Assignment Term
|
identifier :: Assignment Term
|
||||||
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier') <*> (Syntax.Identifier . name <$> source)
|
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source)
|
||||||
|
|
||||||
identifier' :: Assignment Name
|
identifier' :: Assignment Name
|
||||||
identifier' = (symbol Identifier <|> symbol Identifier') *> (name <$> source)
|
identifier' = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source)
|
||||||
|
|
||||||
imaginaryLiteral :: Assignment Term
|
imaginaryLiteral :: Assignment Term
|
||||||
imaginaryLiteral = makeTerm <$> symbol ImaginaryLiteral <*> (Literal.Complex <$> source)
|
imaginaryLiteral = makeTerm <$> symbol ImaginaryLiteral <*> (Literal.Complex <$> source)
|
||||||
|
@ -93,7 +93,7 @@ instance Evaluatable Import where
|
|||||||
paths <- resolveGoImport importPath
|
paths <- resolveGoImport importPath
|
||||||
for_ paths $ \path -> do
|
for_ paths $ \path -> do
|
||||||
traceResolve (unPath importPath) path
|
traceResolve (unPath importPath) path
|
||||||
importedEnv <- fst <$> require path
|
importedEnv <- fst . snd <$> require path
|
||||||
bindAll importedEnv
|
bindAll importedEnv
|
||||||
rvalBox unit
|
rvalBox unit
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ instance Evaluatable QualifiedImport where
|
|||||||
void . letrec' alias $ \addr -> do
|
void . letrec' alias $ \addr -> do
|
||||||
makeNamespace alias addr Nothing . for_ paths $ \p -> do
|
makeNamespace alias addr Nothing . for_ paths $ \p -> do
|
||||||
traceResolve (unPath importPath) p
|
traceResolve (unPath importPath) p
|
||||||
importedEnv <- fst <$> require p
|
importedEnv <- fst . snd <$> require p
|
||||||
bindAll importedEnv
|
bindAll importedEnv
|
||||||
rvalBox unit
|
rvalBox unit
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ include pathTerm f = do
|
|||||||
name <- subtermValue pathTerm >>= asString
|
name <- subtermValue pathTerm >>= asString
|
||||||
path <- resolvePHPName name
|
path <- resolvePHPName name
|
||||||
traceResolve name path
|
traceResolve name path
|
||||||
(importedEnv, v) <- f path
|
(_, (importedEnv, v)) <- f path
|
||||||
bindAll importedEnv
|
bindAll importedEnv
|
||||||
pure (Rval v)
|
pure (Rval v)
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ instance Evaluatable Import where
|
|||||||
|
|
||||||
-- Last module path is the one we want to import
|
-- Last module path is the one we want to import
|
||||||
let path = NonEmpty.last modulePaths
|
let path = NonEmpty.last modulePaths
|
||||||
importedBinds <- fst <$> require path
|
importedBinds <- fst . snd <$> require path
|
||||||
bindAll (select importedBinds)
|
bindAll (select importedBinds)
|
||||||
rvalBox unit
|
rvalBox unit
|
||||||
where
|
where
|
||||||
@ -165,7 +165,7 @@ evalQualifiedImport :: ( AbstractValue address value effects
|
|||||||
)
|
)
|
||||||
=> Name -> ModulePath -> Evaluator address value effects value
|
=> Name -> ModulePath -> Evaluator address value effects value
|
||||||
evalQualifiedImport name path = letrec' name $ \addr -> do
|
evalQualifiedImport name path = letrec' name $ \addr -> do
|
||||||
unit <$ makeNamespace name addr Nothing (bindAll . fst =<< require path)
|
unit <$ makeNamespace name addr Nothing (bindAll . fst . snd =<< require path)
|
||||||
|
|
||||||
newtype QualifiedImport a = QualifiedImport { qualifiedImportFrom :: NonEmpty FilePath }
|
newtype QualifiedImport a = QualifiedImport { qualifiedImportFrom :: NonEmpty FilePath }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
||||||
@ -218,7 +218,7 @@ instance Evaluatable QualifiedAliasedImport where
|
|||||||
alias <- maybeM (throwEvalError NoNameError) (declaredName (subterm aliasTerm))
|
alias <- maybeM (throwEvalError NoNameError) (declaredName (subterm aliasTerm))
|
||||||
rvalBox =<< letrec' alias (\addr -> do
|
rvalBox =<< letrec' alias (\addr -> do
|
||||||
let path = NonEmpty.last modulePaths
|
let path = NonEmpty.last modulePaths
|
||||||
unit <$ makeNamespace alias addr Nothing (void (bindAll . fst =<< require path)))
|
unit <$ makeNamespace alias addr Nothing (void (bindAll . fst . snd =<< require path)))
|
||||||
|
|
||||||
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
|
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
|
||||||
data Ellipsis a = Ellipsis
|
data Ellipsis a = Ellipsis
|
||||||
|
@ -163,6 +163,7 @@ expressionChoices =
|
|||||||
, heredoc
|
, heredoc
|
||||||
, identifier
|
, identifier
|
||||||
, if'
|
, if'
|
||||||
|
, then'
|
||||||
, lambda
|
, lambda
|
||||||
, literal
|
, literal
|
||||||
, method
|
, method
|
||||||
@ -270,7 +271,7 @@ literal =
|
|||||||
(children (inject . Literal.String <$> some (interpolation <|> escapeSequence)) <|> inject . Literal.TextElement <$> source)
|
(children (inject . Literal.String <$> some (interpolation <|> escapeSequence)) <|> inject . Literal.TextElement <$> source)
|
||||||
|
|
||||||
symbol' :: Assignment Term
|
symbol' :: Assignment Term
|
||||||
symbol' = makeTerm' <$> (symbol Symbol <|> symbol Symbol' <|> symbol BareSymbol) <*>
|
symbol' = makeTerm' <$> (symbol Symbol <|> symbol Symbol' <|> symbol Symbol'' <|> symbol BareSymbol) <*>
|
||||||
(children (inject . Literal.Symbol <$> some interpolation) <|> inject . Literal.SymbolElement <$> source)
|
(children (inject . Literal.Symbol <$> some interpolation) <|> inject . Literal.SymbolElement <$> source)
|
||||||
|
|
||||||
interpolation :: Assignment Term
|
interpolation :: Assignment Term
|
||||||
@ -363,14 +364,17 @@ undef = makeTerm <$> symbol Undef <*> children (Expression.Call [] <$> name' <*>
|
|||||||
where name' = makeTerm <$> location <*> (Syntax.Identifier . name <$> source)
|
where name' = makeTerm <$> location <*> (Syntax.Identifier . name <$> source)
|
||||||
|
|
||||||
if' :: Assignment Term
|
if' :: Assignment Term
|
||||||
if' = ifElsif If
|
if' = ifElsif If
|
||||||
<|> makeTerm <$> symbol IfModifier <*> children (flip Statement.If <$> expression <*> expression <*> emptyTerm)
|
<|> makeTerm <$> symbol IfModifier <*> children (flip Statement.If <$> expression <*> expression <*> emptyTerm)
|
||||||
where
|
where
|
||||||
ifElsif s = makeTerm <$> symbol s <*> children (Statement.If <$> expression <*> expressions' <*> (elsif' <|> else' <|> emptyTerm))
|
ifElsif s = makeTerm <$> symbol s <*> children (Statement.If <$> expression <*> expressions' <*> (elsif' <|> else' <|> emptyTerm))
|
||||||
expressions' = makeTerm <$> location <*> manyTermsTill expression (void (symbol Else) <|> void (symbol Elsif) <|> eof)
|
|
||||||
elsif' = postContextualize comment (ifElsif Elsif)
|
elsif' = postContextualize comment (ifElsif Elsif)
|
||||||
|
expressions' = makeTerm <$> location <*> manyTermsTill expression (void (symbol Else) <|> void (symbol Elsif) <|> eof)
|
||||||
else' = postContextualize comment (symbol Else *> children expressions)
|
else' = postContextualize comment (symbol Else *> children expressions)
|
||||||
|
|
||||||
|
then' :: Assignment Term
|
||||||
|
then' = postContextualize comment (symbol Then *> children expressions)
|
||||||
|
|
||||||
unless :: Assignment Term
|
unless :: Assignment Term
|
||||||
unless = makeTerm <$> symbol Unless <*> children (Statement.If <$> invert expression <*> expressions' <*> (else' <|> emptyTerm))
|
unless = makeTerm <$> symbol Unless <*> children (Statement.If <$> invert expression <*> expressions' <*> (else' <|> emptyTerm))
|
||||||
<|> makeTerm <$> symbol UnlessModifier <*> children (flip Statement.If <$> expression <*> invert expression <*> emptyTerm)
|
<|> makeTerm <$> symbol UnlessModifier <*> children (flip Statement.If <$> expression <*> invert expression <*> emptyTerm)
|
||||||
@ -505,17 +509,17 @@ unary = symbol Unary >>= \ location ->
|
|||||||
<|> makeTerm location . Expression.Not <$> children ( symbol AnonBang *> expression )
|
<|> makeTerm location . Expression.Not <$> children ( symbol AnonBang *> expression )
|
||||||
<|> makeTerm location . Expression.Not <$> children ( symbol AnonNot *> expression )
|
<|> makeTerm location . Expression.Not <$> children ( symbol AnonNot *> expression )
|
||||||
<|> makeTerm location <$> children (Expression.Call [] <$> (makeTerm <$> symbol AnonDefinedQuestion <*> (Syntax.Identifier . name <$> source)) <*> some expression <*> emptyTerm)
|
<|> makeTerm location <$> children (Expression.Call [] <$> (makeTerm <$> symbol AnonDefinedQuestion <*> (Syntax.Identifier . name <$> source)) <*> some expression <*> emptyTerm)
|
||||||
<|> makeTerm location . Expression.Negate <$> children ( symbol AnonMinus' *> expression )
|
<|> makeTerm location . Expression.Negate <$> children ( (symbol AnonMinus <|> symbol AnonMinus' <|> symbol AnonMinus'') *> expression )
|
||||||
<|> children ( symbol AnonPlus *> expression )
|
<|> children ( symbol AnonPlus *> expression )
|
||||||
|
|
||||||
-- TODO: Distinguish `===` from `==` ?
|
-- TODO: Distinguish `===` from `==` ?
|
||||||
binary :: Assignment Term
|
binary :: Assignment Term
|
||||||
binary = makeTerm' <$> symbol Binary <*> children (infixTerm expression expression
|
binary = makeTerm' <$> symbol Binary <*> children (infixTerm expression expression
|
||||||
[ (inject .) . Expression.Plus <$ symbol AnonPlus
|
[ (inject .) . Expression.Plus <$ symbol AnonPlus
|
||||||
, (inject .) . Expression.Minus <$ symbol AnonMinus'
|
, (inject .) . Expression.Minus <$ (symbol AnonMinus <|> symbol AnonMinus' <|> symbol AnonMinus'')
|
||||||
, (inject .) . Expression.Times <$ symbol AnonStar'
|
, (inject .) . Expression.Times <$ (symbol AnonStar <|> symbol AnonStar')
|
||||||
, (inject .) . Expression.Power <$ symbol AnonStarStar
|
, (inject .) . Expression.Power <$ symbol AnonStarStar
|
||||||
, (inject .) . Expression.DividedBy <$ symbol AnonSlash
|
, (inject .) . Expression.DividedBy <$ (symbol AnonSlash <|> symbol AnonSlash' <|> symbol AnonSlash'')
|
||||||
, (inject .) . Expression.Modulo <$ symbol AnonPercent
|
, (inject .) . Expression.Modulo <$ symbol AnonPercent
|
||||||
, (inject .) . Expression.And <$ symbol AnonAmpersandAmpersand
|
, (inject .) . Expression.And <$ symbol AnonAmpersandAmpersand
|
||||||
, (inject .) . Ruby.Syntax.LowPrecedenceAnd <$ symbol AnonAnd
|
, (inject .) . Ruby.Syntax.LowPrecedenceAnd <$ symbol AnonAnd
|
||||||
@ -530,7 +534,7 @@ binary = makeTerm' <$> symbol Binary <*> children (infixTerm expression expressi
|
|||||||
-- for this situation.
|
-- for this situation.
|
||||||
, (inject .) . Expression.Equal <$ (symbol AnonEqualEqual <|> symbol AnonEqualEqualEqual)
|
, (inject .) . Expression.Equal <$ (symbol AnonEqualEqual <|> symbol AnonEqualEqualEqual)
|
||||||
, (inject .) . invert Expression.Equal <$ symbol AnonBangEqual
|
, (inject .) . invert Expression.Equal <$ symbol AnonBangEqual
|
||||||
, (inject .) . Expression.LShift <$ symbol AnonLAngleLAngle
|
, (inject .) . Expression.LShift <$ (symbol AnonLAngleLAngle <|> symbol AnonLAngleLAngle')
|
||||||
, (inject .) . Expression.RShift <$ symbol AnonRAngleRAngle
|
, (inject .) . Expression.RShift <$ symbol AnonRAngleRAngle
|
||||||
, (inject .) . Expression.Comparison <$ symbol AnonLAngleEqualRAngle
|
, (inject .) . Expression.Comparison <$ symbol AnonLAngleEqualRAngle
|
||||||
, (inject .) . Expression.LessThan <$ symbol AnonLAngle
|
, (inject .) . Expression.LessThan <$ symbol AnonLAngle
|
||||||
|
@ -98,8 +98,8 @@ doRequire :: ( Member (Boolean value) effects
|
|||||||
doRequire path = do
|
doRequire path = do
|
||||||
result <- lookupModule path
|
result <- lookupModule path
|
||||||
case result of
|
case result of
|
||||||
Nothing -> (,) . fst <$> load path <*> boolean True
|
Nothing -> (,) . fst . snd <$> load path <*> boolean True
|
||||||
Just (env, _) -> (env,) <$> boolean False
|
Just (_, (env, _)) -> (env,) <$> boolean False
|
||||||
|
|
||||||
|
|
||||||
data Load a = Load { loadPath :: a, loadWrap :: Maybe a }
|
data Load a = Load { loadPath :: a, loadWrap :: Maybe a }
|
||||||
@ -132,7 +132,7 @@ doLoad :: ( Member (Boolean value) effects
|
|||||||
doLoad path shouldWrap = do
|
doLoad path shouldWrap = do
|
||||||
path' <- resolveRubyPath path
|
path' <- resolveRubyPath path
|
||||||
traceResolve path path'
|
traceResolve path path'
|
||||||
importedEnv <- fst <$> load path'
|
importedEnv <- fst . snd <$> load path'
|
||||||
unless shouldWrap $ bindAll importedEnv
|
unless shouldWrap $ bindAll importedEnv
|
||||||
boolean Prelude.True -- load always returns true. http://ruby-doc.org/core-2.5.0/Kernel.html#method-i-load
|
boolean Prelude.True -- load always returns true. http://ruby-doc.org/core-2.5.0/Kernel.html#method-i-load
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ false :: Assignment Term
|
|||||||
false = makeTerm <$> symbol Grammar.False <*> (Literal.false <$ rawSource)
|
false = makeTerm <$> symbol Grammar.False <*> (Literal.false <$ rawSource)
|
||||||
|
|
||||||
identifier :: Assignment Term
|
identifier :: Assignment Term
|
||||||
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier') <*> (Syntax.Identifier . name <$> source)
|
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source)
|
||||||
|
|
||||||
class' :: Assignment Term
|
class' :: Assignment Term
|
||||||
class' = makeClass <$> symbol Class <*> children ((,,,,) <$> manyTerm decorator <*> term typeIdentifier <*> (symbol TypeParameters *> children (manyTerm typeParameter') <|> pure []) <*> (classHeritage' <|> pure []) <*> classBodyStatements)
|
class' = makeClass <$> symbol Class <*> children ((,,,,) <$> manyTerm decorator <*> term typeIdentifier <*> (symbol TypeParameters *> children (manyTerm typeParameter') <|> pure []) <*> (classHeritage' <|> pure []) <*> classBodyStatements)
|
||||||
@ -515,7 +515,7 @@ typeAnnotation' :: Assignment Term
|
|||||||
typeAnnotation' = makeTerm <$> symbol TypeAnnotation <*> children (TypeScript.Syntax.Annotation <$> term ty)
|
typeAnnotation' = makeTerm <$> symbol TypeAnnotation <*> children (TypeScript.Syntax.Annotation <$> term ty)
|
||||||
|
|
||||||
typeParameter' :: Assignment Term
|
typeParameter' :: Assignment Term
|
||||||
typeParameter' = makeTerm <$> symbol Grammar.TypeParameter <*> children (TypeScript.Syntax.TypeParameter <$> term identifier <*> term (constraint <|> emptyTerm) <*> term (defaultType <|> emptyTerm))
|
typeParameter' = makeTerm <$> symbol Grammar.TypeParameter <*> children (TypeScript.Syntax.TypeParameter <$> term typeIdentifier <*> term (constraint <|> emptyTerm) <*> term (defaultType <|> emptyTerm))
|
||||||
|
|
||||||
defaultType :: Assignment Term
|
defaultType :: Assignment Term
|
||||||
defaultType = makeTerm <$> symbol Grammar.DefaultType <*> children (TypeScript.Syntax.DefaultType <$> term ty)
|
defaultType = makeTerm <$> symbol Grammar.DefaultType <*> children (TypeScript.Syntax.DefaultType <$> term ty)
|
||||||
@ -593,7 +593,7 @@ typeQuery :: Assignment Term
|
|||||||
typeQuery = makeTerm <$> symbol Grammar.TypeQuery <*> children (TypeScript.Syntax.TypeQuery <$> term (identifier <|> nestedIdentifier))
|
typeQuery = makeTerm <$> symbol Grammar.TypeQuery <*> children (TypeScript.Syntax.TypeQuery <$> term (identifier <|> nestedIdentifier))
|
||||||
|
|
||||||
indexTypeQuery :: Assignment Term
|
indexTypeQuery :: Assignment Term
|
||||||
indexTypeQuery = makeTerm <$> symbol Grammar.IndexTypeQuery <*> children (TypeScript.Syntax.IndexTypeQuery <$> term (typeIdentifier <|> nestedIdentifier))
|
indexTypeQuery = makeTerm <$> symbol Grammar.IndexTypeQuery <*> children (TypeScript.Syntax.IndexTypeQuery <$> term (typeIdentifier <|> nestedTypeIdentifier))
|
||||||
|
|
||||||
thisType :: Assignment Term
|
thisType :: Assignment Term
|
||||||
thisType = makeTerm <$> symbol Grammar.ThisType <*> (TypeScript.Syntax.ThisType <$> source)
|
thisType = makeTerm <$> symbol Grammar.ThisType <*> (TypeScript.Syntax.ThisType <$> source)
|
||||||
@ -620,7 +620,7 @@ constructorTy :: Assignment Term
|
|||||||
constructorTy = makeTerm <$> symbol ConstructorType <*> children (TypeScript.Syntax.Constructor <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> term ty)
|
constructorTy = makeTerm <$> symbol ConstructorType <*> children (TypeScript.Syntax.Constructor <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> term ty)
|
||||||
|
|
||||||
statementBlock :: Assignment Term
|
statementBlock :: Assignment Term
|
||||||
statementBlock = makeTerm <$> symbol StatementBlock <*> children (manyTerm statement)
|
statementBlock = makeTerm <$> symbol StatementBlock <*> children (Statement.Statements <$> manyTerm statement)
|
||||||
|
|
||||||
classBodyStatements :: Assignment Term
|
classBodyStatements :: Assignment Term
|
||||||
classBodyStatements = makeTerm'' <$> symbol ClassBody <*> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as <> [b]) <$> manyTerm decorator <*> term (methodDefinition <|> publicFieldDefinition <|> methodSignature <|> indexSignature <|> abstractMethodSignature))) <*> many comment))
|
classBodyStatements = makeTerm'' <$> symbol ClassBody <*> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as <> [b]) <$> manyTerm decorator <*> term (methodDefinition <|> publicFieldDefinition <|> methodSignature <|> indexSignature <|> abstractMethodSignature))) <*> many comment))
|
||||||
@ -725,7 +725,7 @@ importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> childr
|
|||||||
makeImportTerm loc ([x], from) = makeImportTerm1 loc from x
|
makeImportTerm loc ([x], from) = makeImportTerm1 loc from x
|
||||||
makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs
|
makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs
|
||||||
importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> pure Nothing))
|
importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> pure Nothing))
|
||||||
rawIdentifier = (symbol Identifier <|> symbol Identifier') *> (name <$> source)
|
rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source)
|
||||||
makeNameAliasPair from (Just alias) = (from, alias)
|
makeNameAliasPair from (Just alias) = (from, alias)
|
||||||
makeNameAliasPair from Nothing = (from, from)
|
makeNameAliasPair from Nothing = (from, from)
|
||||||
|
|
||||||
@ -784,7 +784,7 @@ exportStatement = makeTerm <$> symbol Grammar.ExportStatement <*> children (flip
|
|||||||
<|> symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> pure Nothing)
|
<|> symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> pure Nothing)
|
||||||
makeNameAliasPair from (Just alias) = TypeScript.Syntax.Alias from alias
|
makeNameAliasPair from (Just alias) = TypeScript.Syntax.Alias from alias
|
||||||
makeNameAliasPair from Nothing = TypeScript.Syntax.Alias from from
|
makeNameAliasPair from Nothing = TypeScript.Syntax.Alias from from
|
||||||
rawIdentifier = (symbol Identifier <|> symbol Identifier') *> (name <$> source)
|
rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source)
|
||||||
-- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term.
|
-- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term.
|
||||||
fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source)
|
fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source)
|
||||||
|
|
||||||
@ -860,7 +860,7 @@ variableDeclarator =
|
|||||||
where
|
where
|
||||||
makeVarDecl loc (subject, annotations, value) = makeTerm loc (Statement.Assignment [annotations] subject value)
|
makeVarDecl loc (subject, annotations, value) = makeTerm loc (Statement.Assignment [annotations] subject value)
|
||||||
|
|
||||||
requireCall = symbol CallExpression *> children ((symbol Identifier <|> symbol Identifier') *> do
|
requireCall = symbol CallExpression *> children ((symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> do
|
||||||
s <- source
|
s <- source
|
||||||
guard (s == "require")
|
guard (s == "require")
|
||||||
symbol Arguments *> children (symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source))
|
symbol Arguments *> children (symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source))
|
||||||
|
@ -175,4 +175,4 @@ evalRequire :: ( AbstractValue address value effects
|
|||||||
-> Name
|
-> Name
|
||||||
-> Evaluator address value effects value
|
-> Evaluator address value effects value
|
||||||
evalRequire modulePath alias = letrec' alias $ \addr ->
|
evalRequire modulePath alias = letrec' alias $ \addr ->
|
||||||
unit <$ makeNamespace alias addr Nothing (bindAll . fst =<< require modulePath)
|
unit <$ makeNamespace alias addr Nothing (bindAll . fst . snd =<< require modulePath)
|
||||||
|
@ -10,6 +10,7 @@ import Proto3.Suite
|
|||||||
|
|
||||||
import qualified Data.Abstract.Environment as Env
|
import qualified Data.Abstract.Environment as Env
|
||||||
import Data.Abstract.Evaluatable
|
import Data.Abstract.Evaluatable
|
||||||
|
import Control.Abstract.ScopeGraph hiding (Import)
|
||||||
import Data.JSON.Fields
|
import Data.JSON.Fields
|
||||||
import Diffing.Algorithm
|
import Diffing.Algorithm
|
||||||
import Language.TypeScript.Resolution
|
import Language.TypeScript.Resolution
|
||||||
@ -25,7 +26,7 @@ instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
|
|||||||
instance Evaluatable Import where
|
instance Evaluatable Import where
|
||||||
eval (Import symbols importPath) = do
|
eval (Import symbols importPath) = do
|
||||||
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
|
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
|
||||||
importedBinds <- fst <$> require modulePath
|
importedBinds <- fst . snd <$> require modulePath
|
||||||
bindAll (renamed importedBinds)
|
bindAll (renamed importedBinds)
|
||||||
rvalBox unit
|
rvalBox unit
|
||||||
where
|
where
|
||||||
@ -92,7 +93,7 @@ instance Show1 QualifiedExportFrom where liftShowsPrec = genericLiftShowsPrec
|
|||||||
instance Evaluatable QualifiedExportFrom where
|
instance Evaluatable QualifiedExportFrom where
|
||||||
eval (QualifiedExportFrom importPath exportSymbols) = do
|
eval (QualifiedExportFrom importPath exportSymbols) = do
|
||||||
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
|
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
|
||||||
importedBinds <- fst <$> require modulePath
|
importedBinds <- fst . snd <$> require modulePath
|
||||||
-- Look up addresses in importedEnv and insert the aliases with addresses into the exports.
|
-- Look up addresses in importedEnv and insert the aliases with addresses into the exports.
|
||||||
for_ exportSymbols $ \Alias{..} -> do
|
for_ exportSymbols $ \Alias{..} -> do
|
||||||
let address = Env.lookup aliasValue importedBinds
|
let address = Env.lookup aliasValue importedBinds
|
||||||
@ -271,15 +272,24 @@ newtype PredefinedType a = PredefinedType { predefinedType :: T.Text }
|
|||||||
instance Eq1 PredefinedType where liftEq = genericLiftEq
|
instance Eq1 PredefinedType where liftEq = genericLiftEq
|
||||||
instance Ord1 PredefinedType where liftCompare = genericLiftCompare
|
instance Ord1 PredefinedType where liftCompare = genericLiftCompare
|
||||||
instance Show1 PredefinedType where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 PredefinedType where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
-- TODO: Implement Eval instance for PredefinedType
|
||||||
instance Evaluatable PredefinedType
|
instance Evaluatable PredefinedType
|
||||||
|
|
||||||
newtype TypeIdentifier a = TypeIdentifier { contents :: T.Text }
|
newtype TypeIdentifier a = TypeIdentifier { contents :: T.Text }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
||||||
|
|
||||||
|
instance Declarations1 TypeIdentifier where
|
||||||
|
liftDeclaredName _ (TypeIdentifier identifier) = Just (name identifier)
|
||||||
|
|
||||||
instance Eq1 TypeIdentifier where liftEq = genericLiftEq
|
instance Eq1 TypeIdentifier where liftEq = genericLiftEq
|
||||||
instance Ord1 TypeIdentifier where liftCompare = genericLiftCompare
|
instance Ord1 TypeIdentifier where liftCompare = genericLiftCompare
|
||||||
instance Show1 TypeIdentifier where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 TypeIdentifier where liftShowsPrec = genericLiftShowsPrec
|
||||||
instance Evaluatable TypeIdentifier
|
-- TODO: TypeIdentifier shouldn't evaluate to an address in the heap?
|
||||||
|
instance Evaluatable TypeIdentifier where
|
||||||
|
eval TypeIdentifier{..} = do
|
||||||
|
-- Add a reference to the type identifier in the current scope.
|
||||||
|
reference (Reference (name contents)) (Declaration (name contents))
|
||||||
|
rvalBox unit
|
||||||
|
|
||||||
data NestedIdentifier a = NestedIdentifier { left :: !a, right :: !a }
|
data NestedIdentifier a = NestedIdentifier { left :: !a, right :: !a }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
||||||
@ -343,12 +353,21 @@ instance Declarations a => Declarations (EnumDeclaration a) where
|
|||||||
declaredName EnumDeclaration{..} = declaredName enumDeclarationIdentifier
|
declaredName EnumDeclaration{..} = declaredName enumDeclarationIdentifier
|
||||||
|
|
||||||
newtype ExtendsClause a = ExtendsClause { extendsClauses :: [a] }
|
newtype ExtendsClause a = ExtendsClause { extendsClauses :: [a] }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
||||||
|
|
||||||
|
instance Declarations1 ExtendsClause where
|
||||||
|
liftDeclaredName _ (ExtendsClause []) = Nothing
|
||||||
|
liftDeclaredName declaredName (ExtendsClause (x : _)) = declaredName x
|
||||||
|
|
||||||
instance Eq1 ExtendsClause where liftEq = genericLiftEq
|
instance Eq1 ExtendsClause where liftEq = genericLiftEq
|
||||||
instance Ord1 ExtendsClause where liftCompare = genericLiftCompare
|
instance Ord1 ExtendsClause where liftCompare = genericLiftCompare
|
||||||
instance Show1 ExtendsClause where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 ExtendsClause where liftShowsPrec = genericLiftShowsPrec
|
||||||
instance Evaluatable ExtendsClause
|
-- TODO: ExtendsClause shouldn't evaluate to an address in the heap?
|
||||||
|
instance Evaluatable ExtendsClause where
|
||||||
|
eval ExtendsClause{..} = do
|
||||||
|
-- Evaluate subterms
|
||||||
|
traverse_ subtermRef extendsClauses
|
||||||
|
rvalBox unit
|
||||||
|
|
||||||
newtype ArrayType a = ArrayType { arrayType :: a }
|
newtype ArrayType a = ArrayType { arrayType :: a }
|
||||||
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
|
||||||
|
@ -26,7 +26,7 @@ module Semantic.Graph
|
|||||||
|
|
||||||
import Prelude hiding (readFile)
|
import Prelude hiding (readFile)
|
||||||
|
|
||||||
import Analysis.Abstract.Caching
|
import Analysis.Abstract.Caching.FlowInsensitive
|
||||||
import Analysis.Abstract.Collecting
|
import Analysis.Abstract.Collecting
|
||||||
import Analysis.Abstract.Graph as Graph
|
import Analysis.Abstract.Graph as Graph
|
||||||
import Control.Abstract
|
import Control.Abstract
|
||||||
@ -111,8 +111,8 @@ runCallGraph lang includePackages modules package = do
|
|||||||
runGraphAnalysis
|
runGraphAnalysis
|
||||||
= runTermEvaluator @_ @(Hole (Maybe Name) (Located Monovariant)) @Abstract
|
= runTermEvaluator @_ @(Hole (Maybe Name) (Located Monovariant)) @Abstract
|
||||||
. graphing @_ @_ @(Maybe Name) @Monovariant
|
. graphing @_ @_ @(Maybe Name) @Monovariant
|
||||||
. caching
|
|
||||||
. runState (lowerBound @(Heap (Hole (Maybe Name) (Located Monovariant)) Abstract))
|
. runState (lowerBound @(Heap (Hole (Maybe Name) (Located Monovariant)) Abstract))
|
||||||
|
. caching
|
||||||
. runFresh 0
|
. runFresh 0
|
||||||
. resumingLoadError
|
. resumingLoadError
|
||||||
. resumingUnspecialized
|
. resumingUnspecialized
|
||||||
@ -122,6 +122,7 @@ runCallGraph lang includePackages modules package = do
|
|||||||
. resumingAddressError
|
. resumingAddressError
|
||||||
. runReader (packageInfo package)
|
. runReader (packageInfo package)
|
||||||
. runReader (lowerBound @Span)
|
. runReader (lowerBound @Span)
|
||||||
|
. runState (lowerBound @Span)
|
||||||
. runReader (lowerBound @ControlFlowVertex)
|
. runReader (lowerBound @ControlFlowVertex)
|
||||||
. providingLiveSet
|
. providingLiveSet
|
||||||
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult (Hole (Maybe Name) (Located Monovariant)))))))
|
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult (Hole (Maybe Name) (Located Monovariant)))))))
|
||||||
@ -192,6 +193,7 @@ runImportGraph lang (package :: Package term) f =
|
|||||||
. runModules (ModuleTable.modulePaths (packageModules package))
|
. runModules (ModuleTable.modulePaths (packageModules package))
|
||||||
. runTermEvaluator @_ @_ @(Value (Hole (Maybe Name) Precise) (ConcreteEff (Hole (Maybe Name) Precise) _))
|
. runTermEvaluator @_ @_ @(Value (Hole (Maybe Name) Precise) (ConcreteEff (Hole (Maybe Name) Precise) _))
|
||||||
. runReader (packageInfo package)
|
. runReader (packageInfo package)
|
||||||
|
. runState lowerBound
|
||||||
. runReader lowerBound
|
. runReader lowerBound
|
||||||
runAddressEffects
|
runAddressEffects
|
||||||
= Hole.runAllocator Precise.handleAllocator
|
= Hole.runAllocator Precise.handleAllocator
|
||||||
@ -200,6 +202,7 @@ runImportGraph lang (package :: Package term) f =
|
|||||||
|
|
||||||
type ConcreteEffects address rest
|
type ConcreteEffects address rest
|
||||||
= Reader Span
|
= Reader Span
|
||||||
|
': State Span
|
||||||
': Reader PackageInfo
|
': Reader PackageInfo
|
||||||
': Modules address
|
': Modules address
|
||||||
': Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))
|
': Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))
|
||||||
@ -273,6 +276,7 @@ parsePythonPackage parser project = do
|
|||||||
. runModules lowerBound
|
. runModules lowerBound
|
||||||
. runTermEvaluator @_ @_ @(Value (Hole (Maybe Name) Precise) (ConcreteEff (Hole (Maybe Name) Precise) _))
|
. runTermEvaluator @_ @_ @(Value (Hole (Maybe Name) Precise) (ConcreteEff (Hole (Maybe Name) Precise) _))
|
||||||
. runReader (PackageInfo (name "setup") lowerBound)
|
. runReader (PackageInfo (name "setup") lowerBound)
|
||||||
|
. runState lowerBound
|
||||||
. runReader lowerBound
|
. runReader lowerBound
|
||||||
runAddressEffects
|
runAddressEffects
|
||||||
= Hole.runAllocator Precise.handleAllocator
|
= Hole.runAllocator Precise.handleAllocator
|
||||||
@ -322,10 +326,13 @@ parseModule proj parser file = do
|
|||||||
|
|
||||||
withTermSpans :: ( HasField fields Span
|
withTermSpans :: ( HasField fields Span
|
||||||
, Member (Reader Span) effects
|
, Member (Reader Span) effects
|
||||||
|
, Member (State Span) effects -- last evaluated child's span
|
||||||
)
|
)
|
||||||
=> SubtermAlgebra (TermF syntax (Record fields)) term (TermEvaluator term address value effects a)
|
=> SubtermAlgebra (TermF syntax (Record fields)) term (TermEvaluator term address value effects a)
|
||||||
-> SubtermAlgebra (TermF syntax (Record fields)) term (TermEvaluator term address value effects a)
|
-> SubtermAlgebra (TermF syntax (Record fields)) term (TermEvaluator term address value effects a)
|
||||||
withTermSpans recur term = withCurrentSpan (getField (termFAnnotation term)) (recur term)
|
withTermSpans recur term = let
|
||||||
|
updatedSpanAlg = withCurrentSpan (getField (termFAnnotation term)) (recur term)
|
||||||
|
in modifyChildSpan (getField (termFAnnotation term)) updatedSpanAlg
|
||||||
|
|
||||||
resumingResolutionError :: ( Applicative (m effects)
|
resumingResolutionError :: ( Applicative (m effects)
|
||||||
, Effectful m
|
, Effectful m
|
||||||
@ -343,11 +350,12 @@ resumingLoadError :: ( Applicative (m address value effects)
|
|||||||
, Effectful (m address value)
|
, Effectful (m address value)
|
||||||
, Effects effects
|
, Effects effects
|
||||||
, Member Trace effects
|
, Member Trace effects
|
||||||
|
, Ord address
|
||||||
)
|
)
|
||||||
=> m address value (Resumable (BaseError (LoadError address)) ': effects) a
|
=> m address value (Resumable (BaseError (LoadError address)) ': effects) a
|
||||||
-> m address value effects a
|
-> m address value effects a
|
||||||
resumingLoadError = runLoadErrorWith (\ baseError -> traceError "LoadError" baseError *> case baseErrorException baseError of
|
resumingLoadError = runLoadErrorWith (\ baseError -> traceError "LoadError" baseError *> case baseErrorException baseError of
|
||||||
ModuleNotFoundError _ -> pure (lowerBound, hole))
|
ModuleNotFoundError _ -> pure (lowerBound, (lowerBound, hole)))
|
||||||
|
|
||||||
resumingEvalError :: ( Applicative (m effects)
|
resumingEvalError :: ( Applicative (m effects)
|
||||||
, Effectful m
|
, Effectful m
|
||||||
|
@ -104,6 +104,7 @@ repl proxy parser paths = defaultConfig debugOptions >>= \ config -> runM . runD
|
|||||||
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
||||||
. raiseHandler (runModules (ModuleTable.modulePaths (packageModules (snd <$> package))))
|
. raiseHandler (runModules (ModuleTable.modulePaths (packageModules (snd <$> package))))
|
||||||
. runReader (packageInfo package)
|
. runReader (packageInfo package)
|
||||||
|
. runState (lowerBound @Span)
|
||||||
. runReader (lowerBound @Span)
|
. runReader (lowerBound @Span)
|
||||||
$ evaluate proxy id (withTermSpans . step (fmap (\ (x:|_) -> moduleBody x) <$> ModuleTable.toPairs (packageModules (fst <$> package)))) (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules
|
$ evaluate proxy id (withTermSpans . step (fmap (\ (x:|_) -> moduleBody x) <$> ModuleTable.toPairs (packageModules (fst <$> package)))) (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ module Semantic.Util where
|
|||||||
|
|
||||||
import Prelude hiding (id, (.), readFile)
|
import Prelude hiding (id, (.), readFile)
|
||||||
|
|
||||||
import Analysis.Abstract.Caching
|
import Analysis.Abstract.Caching.FlowSensitive
|
||||||
import Analysis.Abstract.Collecting
|
import Analysis.Abstract.Collecting
|
||||||
import Control.Abstract
|
import Control.Abstract
|
||||||
import Control.Category
|
import Control.Category
|
||||||
@ -106,8 +106,9 @@ evaluateProject' (TaskConfig config logger statter) proxy parser paths = either
|
|||||||
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
||||||
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
||||||
(runReader (packageInfo package)
|
(runReader (packageInfo package)
|
||||||
|
(runState (lowerBound @Span)
|
||||||
(runReader (lowerBound @Span)
|
(runReader (lowerBound @Span)
|
||||||
(evaluate proxy id withTermSpans (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules))))))
|
(evaluate proxy id withTermSpans (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules)))))))
|
||||||
|
|
||||||
evaluatePythonProjects proxy parser lang path = runTaskWithOptions debugOptions $ do
|
evaluatePythonProjects proxy parser lang path = runTaskWithOptions debugOptions $ do
|
||||||
project <- readProject Nothing path lang []
|
project <- readProject Nothing path lang []
|
||||||
@ -118,8 +119,9 @@ evaluatePythonProjects proxy parser lang path = runTaskWithOptions debugOptions
|
|||||||
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
|
||||||
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
||||||
(runReader (packageInfo package)
|
(runReader (packageInfo package)
|
||||||
|
(runState (lowerBound @Span)
|
||||||
(runReader (lowerBound @Span)
|
(runReader (lowerBound @Span)
|
||||||
(evaluate proxy id withTermSpans (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules))))))
|
(evaluate proxy id withTermSpans (Precise.runAllocator . Precise.runDeref) (Concrete.runBoolean . Concrete.runFunction coerce coerce) modules)))))))
|
||||||
|
|
||||||
|
|
||||||
evaluateProjectWithCaching proxy parser path = runTaskWithOptions debugOptions $ do
|
evaluateProjectWithCaching proxy parser path = runTaskWithOptions debugOptions $ do
|
||||||
@ -127,10 +129,11 @@ evaluateProjectWithCaching proxy parser path = runTaskWithOptions debugOptions $
|
|||||||
package <- fmap (quieterm . snd) <$> parsePackage parser project
|
package <- fmap (quieterm . snd) <$> parsePackage parser project
|
||||||
modules <- topologicalSort <$> runImportGraphToModules proxy package
|
modules <- topologicalSort <$> runImportGraphToModules proxy package
|
||||||
pure (runReader (packageInfo package)
|
pure (runReader (packageInfo package)
|
||||||
|
(runState (lowerBound @Span)
|
||||||
(runReader (lowerBound @Span)
|
(runReader (lowerBound @Span)
|
||||||
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Monovariant)))))
|
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Monovariant)))))
|
||||||
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
|
||||||
(evaluate proxy id withTermSpans (Monovariant.runAllocator . Monovariant.runDeref) (Type.runBoolean . Type.runFunction) modules)))))
|
(evaluate proxy id withTermSpans (Monovariant.runAllocator . Monovariant.runDeref) (Type.runBoolean . Type.runFunction) modules))))))
|
||||||
|
|
||||||
|
|
||||||
parseFile :: Parser term -> FilePath -> IO term
|
parseFile :: Parser term -> FilePath -> IO term
|
||||||
|
@ -14,7 +14,7 @@ spec config = parallel $ do
|
|||||||
it "imports and wildcard imports" $ do
|
it "imports and wildcard imports" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main.go", "foo/foo.go", "bar/bar.go", "bar/rab.go"]
|
(_, (heap, res)) <- evaluate ["main.go", "foo/foo.go", "bar/bar.go", "bar/rab.go"]
|
||||||
case ModuleTable.lookup "main.go" <$> res of
|
case ModuleTable.lookup "main.go" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "Bar", "Rab", "foo", "main" ]
|
Env.names env `shouldBe` [ "Bar", "Rab", "foo", "main" ]
|
||||||
(derefQName heap ("foo" :| []) env >>= deNamespace heap) `shouldBe` Just ("foo", ["New"])
|
(derefQName heap ("foo" :| []) env >>= deNamespace heap) `shouldBe` Just ("foo", ["New"])
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -22,7 +22,7 @@ spec config = parallel $ do
|
|||||||
it "imports with aliases (and side effects only)" $ do
|
it "imports with aliases (and side effects only)" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main1.go", "foo/foo.go", "bar/bar.go", "bar/rab.go"]
|
(_, (heap, res)) <- evaluate ["main1.go", "foo/foo.go", "bar/bar.go", "bar/rab.go"]
|
||||||
case ModuleTable.lookup "main1.go" <$> res of
|
case ModuleTable.lookup "main1.go" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "f", "main" ]
|
Env.names env `shouldBe` [ "f", "main" ]
|
||||||
(derefQName heap ("f" :| []) env >>= deNamespace heap) `shouldBe` Just ("f", ["New"])
|
(derefQName heap ("f" :| []) env >>= deNamespace heap) `shouldBe` Just ("f", ["New"])
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
@ -15,7 +15,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates include and require" $ do
|
it "evaluates include and require" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main.php", "foo.php", "bar.php"]
|
(_, (heap, res)) <- evaluate ["main.php", "foo.php", "bar.php"]
|
||||||
case ModuleTable.lookup "main.php" <$> res of
|
case ModuleTable.lookup "main.php" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [unit]
|
heapLookupAll addr heap `shouldBe` Just [unit]
|
||||||
Env.names env `shouldBe` [ "bar", "foo" ]
|
Env.names env `shouldBe` [ "bar", "foo" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -23,7 +23,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates include_once and require_once" $ do
|
it "evaluates include_once and require_once" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main_once.php", "foo.php", "bar.php"]
|
(_, (heap, res)) <- evaluate ["main_once.php", "foo.php", "bar.php"]
|
||||||
case ModuleTable.lookup "main_once.php" <$> res of
|
case ModuleTable.lookup "main_once.php" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [unit]
|
heapLookupAll addr heap `shouldBe` Just [unit]
|
||||||
Env.names env `shouldBe` [ "bar", "foo" ]
|
Env.names env `shouldBe` [ "bar", "foo" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -31,7 +31,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates namespaces" $ do
|
it "evaluates namespaces" $ do
|
||||||
(_, (heap, res)) <- evaluate ["namespaces.php"]
|
(_, (heap, res)) <- evaluate ["namespaces.php"]
|
||||||
case ModuleTable.lookup "namespaces.php" <$> res of
|
case ModuleTable.lookup "namespaces.php" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "Foo", "NS1" ]
|
Env.names env `shouldBe` [ "Foo", "NS1" ]
|
||||||
|
|
||||||
(derefQName heap ("NS1" :| []) env >>= deNamespace heap) `shouldBe` Just ("NS1", ["Sub1", "b", "c"])
|
(derefQName heap ("NS1" :| []) env >>= deNamespace heap) `shouldBe` Just ("NS1", ["Sub1", "b", "c"])
|
||||||
|
@ -16,7 +16,7 @@ spec config = parallel $ do
|
|||||||
it "imports" $ do
|
it "imports" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main.py", "a.py", "b/__init__.py", "b/c.py"]
|
(_, (heap, res)) <- evaluate ["main.py", "a.py", "b/__init__.py", "b/c.py"]
|
||||||
case ModuleTable.lookup "main.py" <$> res of
|
case ModuleTable.lookup "main.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldContain` [ "a", "b" ]
|
Env.names env `shouldContain` [ "a", "b" ]
|
||||||
|
|
||||||
(derefQName heap ("a" :| []) env >>= deNamespace heap) `shouldBe` Just ("a", ["foo"])
|
(derefQName heap ("a" :| []) env >>= deNamespace heap) `shouldBe` Just ("a", ["foo"])
|
||||||
@ -27,19 +27,19 @@ spec config = parallel $ do
|
|||||||
it "imports with aliases" $ do
|
it "imports with aliases" $ do
|
||||||
(_, (_, res)) <- evaluate ["main1.py", "a.py", "b/__init__.py", "b/c.py"]
|
(_, (_, res)) <- evaluate ["main1.py", "a.py", "b/__init__.py", "b/c.py"]
|
||||||
case ModuleTable.lookup "main1.py" <$> res of
|
case ModuleTable.lookup "main1.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> Env.names env `shouldContain` [ "b", "e" ]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> Env.names env `shouldContain` [ "b", "e" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "imports using 'from' syntax" $ do
|
it "imports using 'from' syntax" $ do
|
||||||
(_, (_, res)) <- evaluate ["main2.py", "a.py", "b/__init__.py", "b/c.py"]
|
(_, (_, res)) <- evaluate ["main2.py", "a.py", "b/__init__.py", "b/c.py"]
|
||||||
case ModuleTable.lookup "main2.py" <$> res of
|
case ModuleTable.lookup "main2.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> Env.names env `shouldContain` [ "bar", "foo" ]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> Env.names env `shouldContain` [ "bar", "foo" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "imports with relative syntax" $ do
|
it "imports with relative syntax" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main3.py", "c/__init__.py", "c/utils.py"]
|
(_, (heap, res)) <- evaluate ["main3.py", "c/__init__.py", "c/utils.py"]
|
||||||
case ModuleTable.lookup "main3.py" <$> res of
|
case ModuleTable.lookup "main3.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldContain` [ "utils" ]
|
Env.names env `shouldContain` [ "utils" ]
|
||||||
(derefQName heap ("utils" :| []) env >>= deNamespace heap) `shouldBe` Just ("utils", ["to_s"])
|
(derefQName heap ("utils" :| []) env >>= deNamespace heap) `shouldBe` Just ("utils", ["to_s"])
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -47,13 +47,13 @@ spec config = parallel $ do
|
|||||||
it "subclasses" $ do
|
it "subclasses" $ do
|
||||||
(_, (heap, res)) <- evaluate ["subclass.py"]
|
(_, (heap, res)) <- evaluate ["subclass.py"]
|
||||||
case ModuleTable.lookup "subclass.py" <$> res of
|
case ModuleTable.lookup "subclass.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"bar\""]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"bar\""]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "handles multiple inheritance left-to-right" $ do
|
it "handles multiple inheritance left-to-right" $ do
|
||||||
(_, (heap, res)) <- evaluate ["multiple_inheritance.py"]
|
(_, (heap, res)) <- evaluate ["multiple_inheritance.py"]
|
||||||
case ModuleTable.lookup "multiple_inheritance.py" <$> res of
|
case ModuleTable.lookup "multiple_inheritance.py" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"foo!\""]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"foo!\""]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
where
|
where
|
||||||
|
@ -21,7 +21,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates require_relative" $ do
|
it "evaluates require_relative" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main.rb", "foo.rb"]
|
(_, (heap, res)) <- evaluate ["main.rb", "foo.rb"]
|
||||||
case ModuleTable.lookup "main.rb" <$> res of
|
case ModuleTable.lookup "main.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 1)]
|
heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 1)]
|
||||||
Env.names env `shouldContain` [ "foo" ]
|
Env.names env `shouldContain` [ "foo" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -29,7 +29,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates load" $ do
|
it "evaluates load" $ do
|
||||||
(_, (heap, res)) <- evaluate ["load.rb", "foo.rb"]
|
(_, (heap, res)) <- evaluate ["load.rb", "foo.rb"]
|
||||||
case ModuleTable.lookup "load.rb" <$> res of
|
case ModuleTable.lookup "load.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 1)]
|
heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 1)]
|
||||||
Env.names env `shouldContain` [ "foo" ]
|
Env.names env `shouldContain` [ "foo" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -41,7 +41,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates subclass" $ do
|
it "evaluates subclass" $ do
|
||||||
(_, (heap, res)) <- evaluate ["subclass.rb"]
|
(_, (heap, res)) <- evaluate ["subclass.rb"]
|
||||||
case ModuleTable.lookup "subclass.rb" <$> res of
|
case ModuleTable.lookup "subclass.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [String "\"<bar>\""]
|
heapLookupAll addr heap `shouldBe` Just [String "\"<bar>\""]
|
||||||
Env.names env `shouldContain` [ "Bar", "Foo" ]
|
Env.names env `shouldContain` [ "Bar", "Foo" ]
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates modules" $ do
|
it "evaluates modules" $ do
|
||||||
(_, (heap, res)) <- evaluate ["modules.rb"]
|
(_, (heap, res)) <- evaluate ["modules.rb"]
|
||||||
case ModuleTable.lookup "modules.rb" <$> res of
|
case ModuleTable.lookup "modules.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [String "\"<hello>\""]
|
heapLookupAll addr heap `shouldBe` Just [String "\"<hello>\""]
|
||||||
Env.names env `shouldContain` [ "Bar" ]
|
Env.names env `shouldContain` [ "Bar" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -59,43 +59,43 @@ spec config = parallel $ do
|
|||||||
it "handles break correctly" $ do
|
it "handles break correctly" $ do
|
||||||
(_, (heap, res)) <- evaluate ["break.rb"]
|
(_, (heap, res)) <- evaluate ["break.rb"]
|
||||||
case ModuleTable.lookup "break.rb" <$> res of
|
case ModuleTable.lookup "break.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "handles next correctly" $ do
|
it "handles next correctly" $ do
|
||||||
(_, (heap, res)) <- evaluate ["next.rb"]
|
(_, (heap, res)) <- evaluate ["next.rb"]
|
||||||
case ModuleTable.lookup "next.rb" <$> res of
|
case ModuleTable.lookup "next.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 8)]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 8)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "calls functions with arguments" $ do
|
it "calls functions with arguments" $ do
|
||||||
(_, (heap, res)) <- evaluate ["call.rb"]
|
(_, (heap, res)) <- evaluate ["call.rb"]
|
||||||
case ModuleTable.lookup "call.rb" <$> res of
|
case ModuleTable.lookup "call.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 579)]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 579)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates early return statements" $ do
|
it "evaluates early return statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["early-return.rb"]
|
(_, (heap, res)) <- evaluate ["early-return.rb"]
|
||||||
case ModuleTable.lookup "early-return.rb" <$> res of
|
case ModuleTable.lookup "early-return.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 123)]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 123)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "has prelude" $ do
|
it "has prelude" $ do
|
||||||
(_, (heap, res)) <- evaluate ["preluded.rb"]
|
(_, (heap, res)) <- evaluate ["preluded.rb"]
|
||||||
case ModuleTable.lookup "preluded.rb" <$> res of
|
case ModuleTable.lookup "preluded.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"<foo>\""]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [String "\"<foo>\""]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates __LINE__" $ do
|
it "evaluates __LINE__" $ do
|
||||||
(_, (heap, res)) <- evaluate ["line.rb"]
|
(_, (heap, res)) <- evaluate ["line.rb"]
|
||||||
case ModuleTable.lookup "line.rb" <$> res of
|
case ModuleTable.lookup "line.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)]
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "resolves builtins used in the prelude" $ do
|
it "resolves builtins used in the prelude" $ do
|
||||||
(traces, (heap, res)) <- evaluate ["puts.rb"]
|
(traces, (heap, res)) <- evaluate ["puts.rb"]
|
||||||
case ModuleTable.lookup "puts.rb" <$> res of
|
case ModuleTable.lookup "puts.rb" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [Unit]
|
heapLookupAll addr heap `shouldBe` Just [Unit]
|
||||||
traces `shouldContain` [ "\"hello\"" ]
|
traces `shouldContain` [ "\"hello\"" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
@ -17,13 +17,13 @@ spec config = parallel $ do
|
|||||||
it "imports with aliased symbols" $ do
|
it "imports with aliased symbols" $ do
|
||||||
(_, (_, res)) <- evaluate ["main.ts", "foo.ts", "a.ts", "foo/b.ts"]
|
(_, (_, res)) <- evaluate ["main.ts", "foo.ts", "a.ts", "foo/b.ts"]
|
||||||
case ModuleTable.lookup "main.ts" <$> res of
|
case ModuleTable.lookup "main.ts" <$> res of
|
||||||
Right (Just (Module _ (env, _) :| [])) -> Env.names env `shouldBe` [ "bar", "quz" ]
|
Right (Just (Module _ (_, (env, _)) :| [])) -> Env.names env `shouldBe` [ "bar", "quz" ]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "imports with qualified names" $ do
|
it "imports with qualified names" $ do
|
||||||
(_, (heap, res)) <- evaluate ["main1.ts", "foo.ts", "a.ts"]
|
(_, (heap, res)) <- evaluate ["main1.ts", "foo.ts", "a.ts"]
|
||||||
case ModuleTable.lookup "main1.ts" <$> res of
|
case ModuleTable.lookup "main1.ts" <$> res of
|
||||||
Right (Just (Module _ (env, _) :| [])) -> do
|
Right (Just (Module _ (_, (env, _)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "b", "z" ]
|
Env.names env `shouldBe` [ "b", "z" ]
|
||||||
|
|
||||||
(derefQName heap ("b" :| []) env >>= deNamespace heap) `shouldBe` Just ("b", [ "baz", "foo" ])
|
(derefQName heap ("b" :| []) env >>= deNamespace heap) `shouldBe` Just ("b", [ "baz", "foo" ])
|
||||||
@ -33,7 +33,7 @@ spec config = parallel $ do
|
|||||||
it "side effect only imports" $ do
|
it "side effect only imports" $ do
|
||||||
(_, (_, res)) <- evaluate ["main2.ts", "a.ts", "foo.ts"]
|
(_, (_, res)) <- evaluate ["main2.ts", "a.ts", "foo.ts"]
|
||||||
case ModuleTable.lookup "main2.ts" <$> res of
|
case ModuleTable.lookup "main2.ts" <$> res of
|
||||||
Right (Just (Module _ (env, _) :| [])) -> env `shouldBe` lowerBound
|
Right (Just (Module _ (_, (env, _)) :| [])) -> env `shouldBe` lowerBound
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "fails exporting symbols not defined in the module" $ do
|
it "fails exporting symbols not defined in the module" $ do
|
||||||
@ -43,13 +43,13 @@ spec config = parallel $ do
|
|||||||
it "evaluates early return statements" $ do
|
it "evaluates early return statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["early-return.ts"]
|
(_, (heap, res)) <- evaluate ["early-return.ts"]
|
||||||
case ModuleTable.lookup "early-return.ts" <$> res of
|
case ModuleTable.lookup "early-return.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 123.0)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Float (Number.Decimal 123.0)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates sequence expressions" $ do
|
it "evaluates sequence expressions" $ do
|
||||||
(_, (heap, res)) <- evaluate ["sequence-expression.ts"]
|
(_, (heap, res)) <- evaluate ["sequence-expression.ts"]
|
||||||
case ModuleTable.lookup "sequence-expression.ts" <$> res of
|
case ModuleTable.lookup "sequence-expression.ts" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "x" ]
|
Env.names env `shouldBe` [ "x" ]
|
||||||
(derefQName heap ("x" :| []) env) `shouldBe` Just (Value.Float (Number.Decimal 3.0))
|
(derefQName heap ("x" :| []) env) `shouldBe` Just (Value.Float (Number.Decimal 3.0))
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -57,13 +57,13 @@ spec config = parallel $ do
|
|||||||
it "evaluates void expressions" $ do
|
it "evaluates void expressions" $ do
|
||||||
(_, (heap, res)) <- evaluate ["void.ts"]
|
(_, (heap, res)) <- evaluate ["void.ts"]
|
||||||
case ModuleTable.lookup "void.ts" <$> res of
|
case ModuleTable.lookup "void.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Null]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Null]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates delete" $ do
|
it "evaluates delete" $ do
|
||||||
(_, (heap, res)) <- evaluate ["delete.ts"]
|
(_, (heap, res)) <- evaluate ["delete.ts"]
|
||||||
case ModuleTable.lookup "delete.ts" <$> res of
|
case ModuleTable.lookup "delete.ts" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
heapLookupAll addr heap `shouldBe` Just [Unit]
|
heapLookupAll addr heap `shouldBe` Just [Unit]
|
||||||
(derefQName heap ("x" :| []) env) `shouldBe` Nothing
|
(derefQName heap ("x" :| []) env) `shouldBe` Nothing
|
||||||
Env.names env `shouldBe` [ "x" ]
|
Env.names env `shouldBe` [ "x" ]
|
||||||
@ -72,7 +72,7 @@ spec config = parallel $ do
|
|||||||
it "evaluates await" $ do
|
it "evaluates await" $ do
|
||||||
(_, (heap, res)) <- evaluate ["await.ts"]
|
(_, (heap, res)) <- evaluate ["await.ts"]
|
||||||
case ModuleTable.lookup "await.ts" <$> res of
|
case ModuleTable.lookup "await.ts" <$> res of
|
||||||
Right (Just (Module _ (env, addr) :| [])) -> do
|
Right (Just (Module _ (_, (env, addr)) :| [])) -> do
|
||||||
Env.names env `shouldBe` [ "f2" ]
|
Env.names env `shouldBe` [ "f2" ]
|
||||||
(derefQName heap ("y" :| []) env) `shouldBe` Nothing
|
(derefQName heap ("y" :| []) env) `shouldBe` Nothing
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
@ -80,41 +80,41 @@ spec config = parallel $ do
|
|||||||
it "evaluates BOr statements" $ do
|
it "evaluates BOr statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["bor.ts"]
|
(_, (heap, res)) <- evaluate ["bor.ts"]
|
||||||
case ModuleTable.lookup "bor.ts" <$> res of
|
case ModuleTable.lookup "bor.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates BAnd statements" $ do
|
it "evaluates BAnd statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["band.ts"]
|
(_, (heap, res)) <- evaluate ["band.ts"]
|
||||||
case ModuleTable.lookup "band.ts" <$> res of
|
case ModuleTable.lookup "band.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates BXOr statements" $ do
|
it "evaluates BXOr statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["bxor.ts"]
|
(_, (heap, res)) <- evaluate ["bxor.ts"]
|
||||||
case ModuleTable.lookup "bxor.ts" <$> res of
|
case ModuleTable.lookup "bxor.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 3)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates LShift statements" $ do
|
it "evaluates LShift statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["lshift.ts"]
|
(_, (heap, res)) <- evaluate ["lshift.ts"]
|
||||||
case ModuleTable.lookup "lshift.ts" <$> res of
|
case ModuleTable.lookup "lshift.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 4)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates RShift statements" $ do
|
it "evaluates RShift statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["rshift.ts"]
|
(_, (heap, res)) <- evaluate ["rshift.ts"]
|
||||||
case ModuleTable.lookup "rshift.ts" <$> res of
|
case ModuleTable.lookup "rshift.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer 0)]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
it "evaluates Complement statements" $ do
|
it "evaluates Complement statements" $ do
|
||||||
(_, (heap, res)) <- evaluate ["complement.ts"]
|
(_, (heap, res)) <- evaluate ["complement.ts"]
|
||||||
case ModuleTable.lookup "complement.ts" <$> res of
|
case ModuleTable.lookup "complement.ts" <$> res of
|
||||||
Right (Just (Module _ (_, addr) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer (-2))]
|
Right (Just (Module _ (_, (_, addr)) :| [])) -> heapLookupAll addr heap `shouldBe` Just [Value.Integer (Number.Integer (-2))]
|
||||||
other -> expectationFailure (show other)
|
other -> expectationFailure (show other)
|
||||||
|
|
||||||
|
|
||||||
where
|
where
|
||||||
fixtures = "test/fixtures/typescript/analysis/"
|
fixtures = "test/fixtures/typescript/analysis/"
|
||||||
evaluate = evalTypeScriptProject . map (fixtures <>)
|
evaluate = evalTypeScriptProject . map (fixtures <>)
|
||||||
evalTypeScriptProject = testEvaluating <=< evaluateProject' config (Proxy :: Proxy 'Language.TypeScript) typescriptParser
|
evalTypeScriptProject = testEvaluating <=< (evaluateProject' config (Proxy :: Proxy 'Language.TypeScript) typescriptParser)
|
||||||
|
@ -152,7 +152,7 @@ spec = parallel $ do
|
|||||||
it "produces JSON output if there are parse errors" $ do
|
it "produces JSON output if there are parse errors" $ do
|
||||||
blobs <- blobsForPaths (both "ruby/toc/methods.A.rb" "ruby/toc/methods.X.rb")
|
blobs <- blobsForPaths (both "ruby/toc/methods.A.rb" "ruby/toc/methods.X.rb")
|
||||||
output <- runTaskWithOptions (defaultOptions { optionsLogLevel = Nothing }) (runDiff ToCDiffRenderer [blobs])
|
output <- runTaskWithOptions (defaultOptions { optionsLogLevel = Nothing }) (runDiff ToCDiffRenderer [blobs])
|
||||||
runBuilder output `shouldBe` ("{\"changes\":{\"test/fixtures/ruby/toc/methods.A.rb -> test/fixtures/ruby/toc/methods.X.rb\":[{\"span\":{\"start\":[1,1],\"end\":[2,4]},\"category\":\"Method\",\"term\":\"bar\",\"changeType\":\"removed\"},{\"span\":{\"start\":[4,1],\"end\":[5,4]},\"category\":\"Method\",\"term\":\"baz\",\"changeType\":\"removed\"}]},\"errors\":{\"test/fixtures/ruby/toc/methods.A.rb -> test/fixtures/ruby/toc/methods.X.rb\":[{\"span\":{\"start\":[1,1],\"end\":[3,1]},\"error\":\"expected end of input nodes, but got ParseError\",\"language\":\"Ruby\"}]}}\n" :: ByteString)
|
runBuilder output `shouldBe` ("{\"changes\":{\"test/fixtures/ruby/toc/methods.A.rb -> test/fixtures/ruby/toc/methods.X.rb\":[{\"span\":{\"start\":[1,1],\"end\":[2,4]},\"category\":\"Method\",\"term\":\"bar\",\"changeType\":\"removed\"},{\"span\":{\"start\":[4,1],\"end\":[5,4]},\"category\":\"Method\",\"term\":\"baz\",\"changeType\":\"removed\"}]},\"errors\":{\"test/fixtures/ruby/toc/methods.A.rb -> test/fixtures/ruby/toc/methods.X.rb\":[{\"span\":{\"start\":[1,1],\"end\":[2,3]},\"error\":\"expected end of input nodes, but got ParseError\",\"language\":\"Ruby\"}]}}\n" :: ByteString)
|
||||||
|
|
||||||
it "ignores anonymous functions" $ do
|
it "ignores anonymous functions" $ do
|
||||||
blobs <- blobsForPaths (both "ruby/toc/lambda.A.rb" "ruby/toc/lambda.B.rb")
|
blobs <- blobsForPaths (both "ruby/toc/lambda.A.rb" "ruby/toc/lambda.B.rb")
|
||||||
|
@ -118,12 +118,12 @@ type TestEvaluatingErrors = '[ BaseError (ValueError Precise (ConcreteEff Precis
|
|||||||
, BaseError (UnspecializedError Val)
|
, BaseError (UnspecializedError Val)
|
||||||
, BaseError (LoadError Precise)
|
, BaseError (LoadError Precise)
|
||||||
]
|
]
|
||||||
testEvaluating :: Evaluator Precise Val TestEvaluatingEffects (ModuleTable (NonEmpty (Module (ModuleResult Precise))))
|
testEvaluating :: Evaluator Precise Val TestEvaluatingEffects (Span, a)
|
||||||
-> IO
|
-> IO
|
||||||
( [String]
|
( [String]
|
||||||
, ( Heap Precise Val
|
, ( Heap Precise Val
|
||||||
, Either (SomeExc (Data.Sum.Sum TestEvaluatingErrors))
|
, Either (SomeExc (Data.Sum.Sum TestEvaluatingErrors))
|
||||||
(ModuleTable (NonEmpty (Module (ModuleResult Precise))))
|
a
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
testEvaluating
|
testEvaluating
|
||||||
@ -139,6 +139,7 @@ testEvaluating
|
|||||||
. runResolutionError
|
. runResolutionError
|
||||||
. runAddressError
|
. runAddressError
|
||||||
. runValueError @_ @Precise @(ConcreteEff Precise _)
|
. runValueError @_ @Precise @(ConcreteEff Precise _)
|
||||||
|
. fmap snd
|
||||||
|
|
||||||
type Val = Value Precise (ConcreteEff Precise '[Trace, Lift IO])
|
type Val = Value Precise (ConcreteEff Precise '[Trace, Lift IO])
|
||||||
|
|
||||||
@ -153,11 +154,12 @@ namespaceScope :: Heap Precise (Value Precise term)
|
|||||||
-> Value Precise term
|
-> Value Precise term
|
||||||
-> Maybe (Environment Precise)
|
-> Maybe (Environment Precise)
|
||||||
namespaceScope heap ns@(Namespace _ _ _)
|
namespaceScope heap ns@(Namespace _ _ _)
|
||||||
= either (const Nothing) snd
|
= either (const Nothing) (snd . snd)
|
||||||
. run
|
. run
|
||||||
. runFresh 0
|
. runFresh 0
|
||||||
. runAddressError
|
. runAddressError
|
||||||
. runState heap
|
. runState heap
|
||||||
|
. runState (lowerBound @Span)
|
||||||
. runReader (lowerBound @Span)
|
. runReader (lowerBound @Span)
|
||||||
. runReader (ModuleInfo "SpecHelper.hs")
|
. runReader (ModuleInfo "SpecHelper.hs")
|
||||||
. runDeref
|
. runDeref
|
||||||
|
3
test/fixtures/ruby/corpus/if.diffA-B.txt
vendored
3
test/fixtures/ruby/corpus/if.diffA-B.txt
vendored
@ -18,5 +18,6 @@
|
|||||||
{+(If
|
{+(If
|
||||||
{+(Send
|
{+(Send
|
||||||
{+(Identifier)+})+}
|
{+(Identifier)+})+}
|
||||||
{+(Statements)+}
|
{+(Statements
|
||||||
|
{+(Statements)+})+}
|
||||||
{+(Empty)+})+})
|
{+(Empty)+})+})
|
||||||
|
3
test/fixtures/ruby/corpus/if.diffB-A.txt
vendored
3
test/fixtures/ruby/corpus/if.diffB-A.txt
vendored
@ -18,5 +18,6 @@
|
|||||||
{-(If
|
{-(If
|
||||||
{-(Send
|
{-(Send
|
||||||
{-(Identifier)-})-}
|
{-(Identifier)-})-}
|
||||||
{-(Statements)-}
|
{-(Statements
|
||||||
|
{-(Statements)-})-}
|
||||||
{-(Empty)-})-})
|
{-(Empty)-})-})
|
||||||
|
3
test/fixtures/ruby/corpus/if.parseB.txt
vendored
3
test/fixtures/ruby/corpus/if.parseB.txt
vendored
@ -7,5 +7,6 @@
|
|||||||
(If
|
(If
|
||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier))
|
||||||
(Statements)
|
(Statements
|
||||||
|
(Statements))
|
||||||
(Empty)))
|
(Empty)))
|
||||||
|
3
test/fixtures/ruby/corpus/unless.diffA-B.txt
vendored
3
test/fixtures/ruby/corpus/unless.diffA-B.txt
vendored
@ -14,5 +14,6 @@
|
|||||||
{+(Not
|
{+(Not
|
||||||
{+(Send
|
{+(Send
|
||||||
{+(Identifier)+})+})+}
|
{+(Identifier)+})+})+}
|
||||||
{+(Statements)+}
|
{+(Statements
|
||||||
|
{+(Statements)+})+}
|
||||||
{+(Empty)+})+})
|
{+(Empty)+})+})
|
||||||
|
3
test/fixtures/ruby/corpus/unless.diffB-A.txt
vendored
3
test/fixtures/ruby/corpus/unless.diffB-A.txt
vendored
@ -14,5 +14,6 @@
|
|||||||
{-(Not
|
{-(Not
|
||||||
{-(Send
|
{-(Send
|
||||||
{-(Identifier)-})-})-}
|
{-(Identifier)-})-})-}
|
||||||
{-(Statements)-}
|
{-(Statements
|
||||||
|
{-(Statements)-})-}
|
||||||
{-(Empty)-})-})
|
{-(Empty)-})-})
|
||||||
|
3
test/fixtures/ruby/corpus/unless.parseB.txt
vendored
3
test/fixtures/ruby/corpus/unless.parseB.txt
vendored
@ -9,5 +9,6 @@
|
|||||||
(Not
|
(Not
|
||||||
(Send
|
(Send
|
||||||
(Identifier)))
|
(Identifier)))
|
||||||
(Statements)
|
(Statements
|
||||||
|
(Statements))
|
||||||
(Empty)))
|
(Empty)))
|
||||||
|
2
test/fixtures/ruby/corpus/when-else.B.rb
vendored
2
test/fixtures/ruby/corpus/when-else.B.rb
vendored
@ -1,6 +1,8 @@
|
|||||||
case foo
|
case foo
|
||||||
when bar
|
when bar
|
||||||
baz
|
baz
|
||||||
|
when x
|
||||||
|
when y
|
||||||
else
|
else
|
||||||
qoz
|
qoz
|
||||||
end
|
end
|
||||||
|
38
test/fixtures/ruby/corpus/when-else.diffA-B.txt
vendored
38
test/fixtures/ruby/corpus/when-else.diffA-B.txt
vendored
@ -3,23 +3,33 @@
|
|||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier))
|
||||||
(Statements
|
(Statements
|
||||||
|
{+(Pattern
|
||||||
|
{+(Statements
|
||||||
|
{+(Send
|
||||||
|
{+(Identifier)+})+})+}
|
||||||
|
{+(Statements
|
||||||
|
{+(Send
|
||||||
|
{+(Identifier)+})+})+})+}
|
||||||
(Pattern
|
(Pattern
|
||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
{ (Identifier)
|
{ (Identifier)
|
||||||
->(Identifier) }))
|
->(Identifier) }))
|
||||||
(Statements
|
(Statements))
|
||||||
|
{+(Pattern
|
||||||
|
{+(Statements
|
||||||
{+(Send
|
{+(Send
|
||||||
{+(Identifier)+})+}
|
{+(Identifier)+})+})+}
|
||||||
{+(Send
|
{+(Statements)+})+}
|
||||||
{+(Identifier)+})+}
|
{+(Send
|
||||||
{-(Pattern
|
{+(Identifier)+})+}
|
||||||
{-(Statements
|
{-(Pattern
|
||||||
{-(Send
|
{-(Statements
|
||||||
{-(Identifier)-})-}
|
{-(Send
|
||||||
{-(Send
|
{-(Identifier)-})-}
|
||||||
{-(Identifier)-})-})-}
|
{-(Send
|
||||||
{-(Statements
|
{-(Identifier)-})-})-}
|
||||||
{-(Send
|
{-(Statements
|
||||||
{-(Identifier)-})-}
|
{-(Send
|
||||||
{-(Statements)-})-})-})))))
|
{-(Identifier)-})-})-})-}
|
||||||
|
{-(Statements)-})))
|
||||||
|
35
test/fixtures/ruby/corpus/when-else.diffB-A.txt
vendored
35
test/fixtures/ruby/corpus/when-else.diffB-A.txt
vendored
@ -3,23 +3,30 @@
|
|||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier))
|
||||||
(Statements
|
(Statements
|
||||||
|
{+(Pattern
|
||||||
|
{+(Statements
|
||||||
|
{+(Send
|
||||||
|
{+(Identifier)+})+})+}
|
||||||
|
{+(Statements)+})+}
|
||||||
(Pattern
|
(Pattern
|
||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
{ (Identifier)
|
(Identifier))
|
||||||
->(Identifier) }))
|
{+(Send
|
||||||
|
{+(Identifier)+})+})
|
||||||
(Statements
|
(Statements
|
||||||
{+(Pattern
|
(Send
|
||||||
{+(Statements
|
(Identifier))))
|
||||||
{+(Send
|
{+(Statements)+}
|
||||||
{+(Identifier)+})+}
|
{-(Pattern
|
||||||
{+(Send
|
{-(Statements
|
||||||
{+(Identifier)+})+})+}
|
|
||||||
{+(Statements
|
|
||||||
{+(Send
|
|
||||||
{+(Identifier)+})+}
|
|
||||||
{+(Statements)+})+})+}
|
|
||||||
{-(Send
|
{-(Send
|
||||||
{-(Identifier)-})-}
|
{-(Identifier)-})-})-}
|
||||||
|
{-(Statements)-})-}
|
||||||
|
{-(Pattern
|
||||||
|
{-(Statements
|
||||||
{-(Send
|
{-(Send
|
||||||
{-(Identifier)-})-})))))
|
{-(Identifier)-})-})-}
|
||||||
|
{-(Statements)-})-}
|
||||||
|
{-(Send
|
||||||
|
{-(Identifier)-})-})))
|
||||||
|
20
test/fixtures/ruby/corpus/when-else.parseA.txt
vendored
20
test/fixtures/ruby/corpus/when-else.parseA.txt
vendored
@ -7,14 +7,14 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
(Identifier)))
|
(Identifier)))
|
||||||
|
(Statements))
|
||||||
|
(Pattern
|
||||||
(Statements
|
(Statements
|
||||||
(Pattern
|
(Send
|
||||||
(Statements
|
(Identifier))
|
||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier)))
|
||||||
(Send
|
(Statements
|
||||||
(Identifier)))
|
(Send
|
||||||
(Statements
|
(Identifier))))
|
||||||
(Send
|
(Statements))))
|
||||||
(Identifier))
|
|
||||||
(Statements))))))))
|
|
||||||
|
14
test/fixtures/ruby/corpus/when-else.parseB.txt
vendored
14
test/fixtures/ruby/corpus/when-else.parseB.txt
vendored
@ -9,6 +9,16 @@
|
|||||||
(Identifier)))
|
(Identifier)))
|
||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier))))
|
||||||
|
(Pattern
|
||||||
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
(Identifier)))))))
|
(Identifier)))
|
||||||
|
(Statements))
|
||||||
|
(Pattern
|
||||||
|
(Statements
|
||||||
|
(Send
|
||||||
|
(Identifier)))
|
||||||
|
(Statements))
|
||||||
|
(Send
|
||||||
|
(Identifier)))))
|
||||||
|
18
test/fixtures/ruby/corpus/when.diffA-B.txt
vendored
18
test/fixtures/ruby/corpus/when.diffA-B.txt
vendored
@ -8,17 +8,17 @@
|
|||||||
(Send
|
(Send
|
||||||
(Identifier)))
|
(Identifier)))
|
||||||
(Statements
|
(Statements
|
||||||
|
{+(Send
|
||||||
|
{+(Identifier)+})+}))
|
||||||
|
{+(Pattern
|
||||||
|
{+(Statements
|
||||||
{+(Send
|
{+(Send
|
||||||
{+(Identifier)+})+}
|
{+(Identifier)+})+}
|
||||||
{+(Pattern
|
{+(Send
|
||||||
{+(Statements
|
{+(Identifier)+})+})+}
|
||||||
{+(Send
|
{+(Statements)+})+}
|
||||||
{+(Identifier)+})+}
|
{+(Send
|
||||||
{+(Send
|
{+(Identifier)+})+}))
|
||||||
{+(Identifier)+})+})+}
|
|
||||||
{+(Statements
|
|
||||||
{+(Send
|
|
||||||
{+(Identifier)+})+})+})+}))))
|
|
||||||
{-(Match
|
{-(Match
|
||||||
{-(Empty)-}
|
{-(Empty)-}
|
||||||
{-(Statements
|
{-(Statements
|
||||||
|
18
test/fixtures/ruby/corpus/when.diffB-A.txt
vendored
18
test/fixtures/ruby/corpus/when.diffB-A.txt
vendored
@ -8,17 +8,17 @@
|
|||||||
(Send
|
(Send
|
||||||
(Identifier)))
|
(Identifier)))
|
||||||
(Statements
|
(Statements
|
||||||
|
{-(Send
|
||||||
|
{-(Identifier)-})-}))
|
||||||
|
{-(Pattern
|
||||||
|
{-(Statements
|
||||||
{-(Send
|
{-(Send
|
||||||
{-(Identifier)-})-}
|
{-(Identifier)-})-}
|
||||||
{-(Pattern
|
{-(Send
|
||||||
{-(Statements
|
{-(Identifier)-})-})-}
|
||||||
{-(Send
|
{-(Statements)-})-}
|
||||||
{-(Identifier)-})-}
|
{-(Send
|
||||||
{-(Send
|
{-(Identifier)-})-}))
|
||||||
{-(Identifier)-})-})-}
|
|
||||||
{-(Statements
|
|
||||||
{-(Send
|
|
||||||
{-(Identifier)-})-})-})-}))))
|
|
||||||
{+(Match
|
{+(Match
|
||||||
{+(Empty)+}
|
{+(Empty)+}
|
||||||
{+(Statements
|
{+(Statements
|
||||||
|
18
test/fixtures/ruby/corpus/when.parseB.txt
vendored
18
test/fixtures/ruby/corpus/when.parseB.txt
vendored
@ -7,15 +7,15 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
(Identifier)))
|
(Identifier)))
|
||||||
|
(Statements
|
||||||
|
(Send
|
||||||
|
(Identifier))))
|
||||||
|
(Pattern
|
||||||
(Statements
|
(Statements
|
||||||
(Send
|
(Send
|
||||||
(Identifier))
|
(Identifier))
|
||||||
(Pattern
|
(Send
|
||||||
(Statements
|
(Identifier)))
|
||||||
(Send
|
(Statements))
|
||||||
(Identifier))
|
(Send
|
||||||
(Send
|
(Identifier)))))
|
||||||
(Identifier)))
|
|
||||||
(Statements
|
|
||||||
(Send
|
|
||||||
(Identifier)))))))))
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Class
|
(Class
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
{ (Identifier)
|
{ (TypeIdentifier)
|
||||||
->(Identifier) }
|
->(TypeIdentifier) }
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty))
|
(Empty))
|
||||||
{ (TypeIdentifier)
|
{ (TypeIdentifier)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Class
|
(Class
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
{ (Identifier)
|
{ (TypeIdentifier)
|
||||||
->(Identifier) }
|
->(TypeIdentifier) }
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty))
|
(Empty))
|
||||||
{ (TypeIdentifier)
|
{ (TypeIdentifier)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Class
|
(Class
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
(Identifier)
|
(TypeIdentifier)
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty))
|
(Empty))
|
||||||
(TypeIdentifier)
|
(TypeIdentifier)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(Statements
|
(Statements
|
||||||
(Class
|
(Class
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
(Identifier)
|
(TypeIdentifier)
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty))
|
(Empty))
|
||||||
(TypeIdentifier)
|
(TypeIdentifier)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
{+(TypeIdentifier)+})+}
|
{+(TypeIdentifier)+})+}
|
||||||
{-(TypeParameters
|
{-(TypeParameters
|
||||||
{-(TypeParameter
|
{-(TypeParameter
|
||||||
{-(Identifier)-}
|
{-(TypeIdentifier)-}
|
||||||
{-(Empty)-}
|
{-(Empty)-}
|
||||||
{-(Empty)-})-})-}
|
{-(Empty)-})-})-}
|
||||||
{-(Annotation
|
{-(Annotation
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
(Function
|
(Function
|
||||||
{+(TypeParameters
|
{+(TypeParameters
|
||||||
{+(TypeParameter
|
{+(TypeParameter
|
||||||
{+(Identifier)+}
|
{+(TypeIdentifier)+}
|
||||||
{+(Empty)+}
|
{+(Empty)+}
|
||||||
{+(Empty)+})+})+}
|
{+(Empty)+})+})+}
|
||||||
{+(Annotation
|
{+(Annotation
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
(Function
|
(Function
|
||||||
(TypeParameters
|
(TypeParameters
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
(Identifier)
|
(TypeIdentifier)
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty)))
|
(Empty)))
|
||||||
(Annotation
|
(Annotation
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{+(Empty)+}
|
{+(Empty)+}
|
||||||
{-(TypeParameters
|
{-(TypeParameters
|
||||||
{-(TypeParameter
|
{-(TypeParameter
|
||||||
{-(Identifier)-}
|
{-(TypeIdentifier)-}
|
||||||
{-(Empty)-}
|
{-(Empty)-}
|
||||||
{-(Empty)-})-})-}
|
{-(Empty)-})-})-}
|
||||||
{ (TypeIdentifier)
|
{ (TypeIdentifier)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
(InterfaceDeclaration
|
(InterfaceDeclaration
|
||||||
{+(TypeParameters
|
{+(TypeParameters
|
||||||
{+(TypeParameter
|
{+(TypeParameter
|
||||||
{+(Identifier)+}
|
{+(TypeIdentifier)+}
|
||||||
{+(Empty)+}
|
{+(Empty)+}
|
||||||
{+(Empty)+})+})+}
|
{+(Empty)+})+})+}
|
||||||
{-(Empty)-}
|
{-(Empty)-}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
(InterfaceDeclaration
|
(InterfaceDeclaration
|
||||||
(TypeParameters
|
(TypeParameters
|
||||||
(TypeParameter
|
(TypeParameter
|
||||||
(Identifier)
|
(TypeIdentifier)
|
||||||
(Empty)
|
(Empty)
|
||||||
(Empty)))
|
(Empty)))
|
||||||
(TypeIdentifier)
|
(TypeIdentifier)
|
||||||
|
2
vendor/haskell-tree-sitter
vendored
2
vendor/haskell-tree-sitter
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 75f9ddd2deb992d944a8485fe9b0cc7c84911c31
|
Subproject commit 09ff8a81cd92a696939eb82e0c33111bde3f0376
|
Loading…
Reference in New Issue
Block a user