1
1
mirror of https://github.com/github/semantic.git synced 2024-11-28 18:23:44 +03:00

Fix terrible bug associated with environment comparisons being false

This commit is contained in:
Patrick Thomson 2018-07-03 14:29:47 -04:00
parent 1eed347da6
commit 0ca991f0dd
9 changed files with 47 additions and 8 deletions

View File

@ -92,8 +92,9 @@ convergingModules :: ( AbstractValue address value effects
convergingModules recur m = do convergingModules recur m = do
c <- getConfiguration (subterm (moduleBody m)) c <- getConfiguration (subterm (moduleBody m))
-- Convergence here is predicated upon an Eq instance, not α-equivalence -- Convergence here is predicated upon an Eq instance, not α-equivalence
cache <- converge lowerBound (\ prevCache -> isolateCache . raiseHandler locally $ do cache <- converge lowerBound (\ prevCache -> isolateCache $ do
TermEvaluator (putHeap (configurationHeap c)) TermEvaluator (putHeap (configurationHeap c))
TermEvaluator (putEnv (configurationEnvironment c))
-- We need to reset fresh generation so that this invocation converges. -- We need to reset fresh generation so that this invocation converges.
resetFresh 0 $ resetFresh 0 $
-- This is subtle: though the calling context supports nondeterminism, we want -- This is subtle: though the calling context supports nondeterminism, we want
@ -102,8 +103,9 @@ convergingModules recur m = do
-- would never complete). We dont need to use the values, so we 'gather' the -- would never complete). We dont need to use the values, so we 'gather' the
-- nondeterministic values into @()@. -- nondeterministic values into @()@.
withOracle prevCache (gatherM (const ()) (recur m))) withOracle prevCache (gatherM (const ()) (recur m)))
TermEvaluator (address =<< runTermEvaluator (maybe empty scatter (cacheLookup c cache)))
-- TODO: We're hitting an infinite loop here, c.f test/fixtures/ruby/analysis/graphing/include-file-with-undefined-call
TermEvaluator (address =<< runTermEvaluator (maybe empty scatter (cacheLookup c cache)))
-- | Iterate a monadic action starting from some initial seed until the results converge. -- | Iterate a monadic action starting from some initial seed until the results converge.
-- --

View File

@ -49,7 +49,7 @@ graphingTerms :: ( Element Syntax.Identifier syntax
, Member (Reader ModuleInfo) effects , Member (Reader ModuleInfo) effects
, Member (Env (Hole (Located address))) effects , Member (Env (Hole (Located address))) effects
, Member (State (Graph Vertex)) effects , Member (State (Graph Vertex)) effects
, term ~ Term (Sum syntax) ann , Base term ~ TermF (Sum syntax) ann
) )
=> SubtermAlgebra (Base term) term (TermEvaluator term (Hole (Located address)) value effects a) => SubtermAlgebra (Base term) term (TermEvaluator term (Hole (Located address)) value effects a)
-> SubtermAlgebra (Base term) term (TermEvaluator term (Hole (Located address)) value effects a) -> SubtermAlgebra (Base term) term (TermEvaluator term (Hole (Located address)) value effects a)

View File

@ -3,6 +3,7 @@ module Control.Abstract.Environment
( Environment ( Environment
, Exports , Exports
, getEnv , getEnv
, putEnv
, export , export
, lookupEnv , lookupEnv
, bind , bind
@ -29,6 +30,10 @@ import Prologue
getEnv :: Member (Env address) effects => Evaluator address value effects (Environment address) getEnv :: Member (Env address) effects => Evaluator address value effects (Environment address)
getEnv = send GetEnv getEnv = send GetEnv
-- | This is only for use in Analysis.Abstract.Caching.
putEnv :: Member (Env address) effects => Environment address -> Evaluator address value effects ()
putEnv = send . PutEnv
-- | Add an export to the global export state. -- | Add an export to the global export state.
export :: Member (Env address) effects => Name -> Name -> Maybe address -> Evaluator address value effects () export :: Member (Env address) effects => Name -> Name -> Maybe address -> Evaluator address value effects ()
export name alias addr = send (Export name alias addr) export name alias addr = send (Export name alias addr)
@ -67,6 +72,8 @@ data Env address return where
Pop :: Env address () Pop :: Env address ()
GetEnv :: Env address (Environment address) GetEnv :: Env address (Environment address)
Export :: Name -> Name -> Maybe address -> Env address () Export :: Name -> Name -> Maybe address -> Env address ()
PutEnv :: Environment address -> Env address ()
handleEnv :: forall address effects value result handleEnv :: forall address effects value result
. ( Member (State (Environment address)) effects . ( Member (State (Environment address)) effects
@ -81,6 +88,7 @@ handleEnv = \case
Push -> modify (Env.push @address) Push -> modify (Env.push @address)
Pop -> modify (Env.pop @address) Pop -> modify (Env.pop @address)
GetEnv -> get GetEnv -> get
PutEnv e -> put e
Export name alias addr -> modify (Exports.insert name alias addr) Export name alias addr -> modify (Exports.insert name alias addr)
runEnv :: Environment address runEnv :: Environment address

View File

@ -32,6 +32,8 @@ cacheSet key value = Cache . Monoidal.insert key value . unCache
cacheInsert :: Cacheable term address cell value => Configuration term address cell value -> Cached address cell value -> Cache term address cell value -> Cache term address cell value cacheInsert :: Cacheable term address cell value => Configuration term address cell value -> Cached address cell value -> Cache term address cell value -> Cache term address cell value
cacheInsert = curry cons cacheInsert = curry cons
cacheKeys :: Cacheable term address cell value => Cache term address cell value -> [Configuration term address cell value]
cacheKeys = Monoidal.keys . unCache
instance (Show term, Show address, Show (cell value), Show value) => Show (Cache term address cell value) where instance (Show term, Show address, Show (cell value), Show value) => Show (Cache term address cell value) where
showsPrec d = showsUnaryWith showsPrec "Cache" d . map (second toList) . Monoidal.pairs . unCache showsPrec d = showsUnaryWith showsPrec "Cache" d . map (second toList) . Monoidal.pairs . unCache

View File

@ -8,6 +8,7 @@ module Data.Map.Monoidal
, insert , insert
, filterWithKey , filterWithKey
, pairs , pairs
, keys
, module Reducer , module Reducer
) where ) where
@ -37,6 +38,8 @@ insert key value = Map . Map.insert key value . unMap
filterWithKey :: (key -> value -> Bool) -> Map key value -> Map key value filterWithKey :: (key -> value -> Bool) -> Map key value -> Map key value
filterWithKey f = Map . Map.filterWithKey f . unMap filterWithKey f = Map . Map.filterWithKey f . unMap
keys :: Map key value -> [key]
keys = map fst . pairs
pairs :: Map key value -> [(key, value)] pairs :: Map key value -> [(key, value)]
pairs = Map.toList . unMap pairs = Map.toList . unMap

View File

@ -1,6 +1,7 @@
{-# LANGUAGE GADTs, ScopedTypeVariables, TypeOperators #-} {-# LANGUAGE GADTs, ScopedTypeVariables, TypeOperators #-}
module Semantic.Graph module Semantic.Graph
( runGraph ( runGraph
, runCallGraph
, runImportGraph , runImportGraph
, GraphType(..) , GraphType(..)
, Graph , Graph
@ -59,7 +60,7 @@ runGraph ImportGraph _ project
runGraph CallGraph includePackages project runGraph CallGraph includePackages project
| SomeAnalysisParser parser lang <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do | SomeAnalysisParser parser lang <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do
package <- parsePackage parser project package <- parsePackage parser project
modules <- runImportGraph lang package modules <- topologicalSort <$> runImportGraph lang package
runCallGraph lang includePackages modules package runCallGraph lang includePackages modules package
runCallGraph :: ( HasField ann Span runCallGraph :: ( HasField ann Span
@ -68,7 +69,10 @@ runCallGraph :: ( HasField ann Span
, Apply Ord1 syntax , Apply Ord1 syntax
, Apply Functor syntax , Apply Functor syntax
, Ord (Record ann) , Ord (Record ann)
, term ~ Term (Sum syntax) (Record ann) , Show term
, Base term ~ TermF (Sum syntax) (Record ann)
, Ord term
, Corecursive term
, Declarations term , Declarations term
, Evaluatable (Base term) , Evaluatable (Base term)
, FreeVariables term , FreeVariables term
@ -78,12 +82,12 @@ runCallGraph :: ( HasField ann Span
) )
=> Proxy lang => Proxy lang
-> Bool -> Bool
-> Graph (Module term) -> [Module term]
-> Package term -> Package term
-> Eff effs (Graph Vertex) -> Eff effs (Graph Vertex)
runCallGraph lang includePackages modules package = do runCallGraph lang includePackages modules package = do
let analyzeTerm = withTermSpans . graphingTerms . cachingTerms let analyzeTerm = withTermSpans . graphingTerms . cachingTerms
analyzeModule = (if includePackages then graphingPackages else id) . convergingModules analyzeModule = (if includePackages then graphingPackages else id) . convergingModules . graphingModules
extractGraph (((_, graph), _), _) = simplify graph extractGraph (((_, graph), _), _) = simplify graph
runGraphAnalysis runGraphAnalysis
= run = run
@ -106,7 +110,7 @@ runCallGraph lang includePackages modules package = do
. fmap fst . fmap fst
. runState (lowerBound @(ModuleTable (NonEmpty (Module (Hole (Located Monovariant), Environment (Hole (Located Monovariant))))))) . runState (lowerBound @(ModuleTable (NonEmpty (Module (Hole (Located Monovariant), Environment (Hole (Located Monovariant)))))))
. raiseHandler (runModules (ModuleTable.modulePaths (packageModules package))) . raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
extractGraph <$> analyze runGraphAnalysis (evaluate lang analyzeModule analyzeTerm (topologicalSort modules)) extractGraph <$> analyze runGraphAnalysis (evaluate lang analyzeModule analyzeTerm modules)
runImportGraph :: ( Declarations term runImportGraph :: ( Declarations term

View File

@ -98,6 +98,16 @@ evalTypeScriptProject = justEvaluating <=< evaluateProject (Proxy :: Proxy 'Lang
typecheckGoFile = checking <=< evaluateProjectWithCaching (Proxy :: Proxy 'Language.Go) goParser Language.Go typecheckGoFile = checking <=< evaluateProjectWithCaching (Proxy :: Proxy 'Language.Go) goParser Language.Go
callGraphRubyProject paths = runTaskWithOptions debugOptions $ do
let proxy = Proxy @'Language.Ruby
let lang = Language.Ruby
blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths)
package <- parsePackage rubyParser (Project (takeDirectory (maybe "/" fst (uncons paths))) blobs lang [])
modules <- topologicalSort <$> runImportGraph proxy package
x <- runCallGraph proxy False modules package
pure (x, modules)
-- Evaluate a project consisting of the listed paths. -- Evaluate a project consisting of the listed paths.
evaluateProject proxy parser lang paths = runTaskWithOptions debugOptions $ do evaluateProject proxy parser lang paths = runTaskWithOptions debugOptions $ do
blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths) blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths)

View File

@ -0,0 +1,7 @@
require './target'
def go()
"done"
end
go()

View File

@ -0,0 +1,3 @@
barf()
def foo(); end