1
1
mirror of https://github.com/github/semantic.git synced 2024-12-19 12:51:52 +03:00

Make Evaluator use effectful trace rather than Debug.Trace.

This commit is contained in:
Patrick Thomson 2018-05-07 14:15:47 -04:00
parent 3b497bd278
commit bedba61867
9 changed files with 69 additions and 27 deletions

View File

@ -7,6 +7,8 @@ module Control.Abstract.Evaluator
, ModuleTable
, Exports
, JumpTable
-- * Trace
, traceE
-- * Environment
, getEnv
, putEnv
@ -70,6 +72,7 @@ module Control.Abstract.Evaluator
, module Control.Monad.Effect.Reader
, module Control.Monad.Effect.Resumable
, module Control.Monad.Effect.State
, Trace (..)
, Eff.relay
) where
@ -81,6 +84,7 @@ import Control.Monad.Effect.NonDet
import Control.Monad.Effect.Reader hiding (runReader)
import Control.Monad.Effect.Resumable
import Control.Monad.Effect.State hiding (runState)
import Control.Monad.Effect.Trace
import Data.Abstract.Address
import Data.Abstract.Configuration
import Data.Abstract.Environment as Env
@ -95,7 +99,7 @@ import qualified Data.IntMap as IntMap
import Data.Semigroup.Reducer
import Data.Semilattice.Lower
import Prelude hiding (fail)
import Prologue
import Prologue hiding (trace)
newtype Evaluator location term value effects a = Evaluator { runEvaluator :: Eff.Eff effects a }
deriving (Applicative, Effectful, Functor, Monad)
@ -123,6 +127,10 @@ modifyEnv = raise . modify'
withEnv :: Member (State (Environment location value)) effects => Environment location value -> Evaluator location term value effects a -> Evaluator location term value effects a
withEnv = raiseHandler . localState . const
-- TODO: move and generalize
traceE :: Member Trace effects => String -> Evaluator location term value effects ()
traceE = raise . trace
-- | Retrieve the default environment.
defaultEnvironment :: Member (Reader (Environment location value)) effects => Evaluator location term value effects (Environment location value)

View File

@ -81,6 +81,7 @@ type EvaluatableConstraints location term value effects =
, State (Exports location value)
, State (Heap location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
, Reducer value (Cell location value)
)
@ -253,8 +254,8 @@ resolve names = do
tbl <- askModuleTable
pure $ find (`ModuleTable.member` tbl) names
traceResolve :: (Show a, Show b) => a -> b -> c -> c
traceResolve name path = trace ("resolved " <> show name <> " -> " <> show path)
traceResolve :: (Show a, Show b, Member Trace effects) => a -> b -> Evaluator location term value effects ()
traceResolve name path = traceE ("resolved " <> show name <> " -> " <> show path)
listModulesInDir :: Member (Reader (ModuleTable [Module term])) effects
=> FilePath
@ -271,6 +272,7 @@ require :: Members '[ EvalModule term value
, State (Environment location value)
, State (Exports location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
=> ModulePath
-> Evaluator location term value effects (Maybe (Environment location value, value))
@ -286,6 +288,7 @@ load :: Members '[ EvalModule term value
, State (Environment location value)
, State (Exports location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
=> ModulePath
-> Evaluator location term value effects (Maybe (Environment location value, value))
@ -300,7 +303,7 @@ load name = askModuleTable >>= maybeM notFound . ModuleTable.lookup name >>= run
then trace ("load (skip evaluating, circular load): " <> show mPath) (pure Nothing)
else do
v <- localLoadStack (loadStackPush (moduleInfo x)) (trace ("load (evaluating): " <> show mPath) (evaluateModule x))
traceM ("load done:" <> show mPath)
traceE ("load done:" <> show mPath)
env <- filterEnv <$> getExports <*> getEnv
modifyModuleTable (ModuleTable.insert name (env, v))
pure (Just (env, v))
@ -331,6 +334,7 @@ evaluatePackageWith :: ( Evaluatable (Base term)
, Members '[ Fail
, Reader (Environment location value)
, State (Environment location value)
, Trace
] effects
, Recursive term
, termEffects ~ (LoopControl value ': Return value ': EvalClosure term value ': moduleEffects)
@ -350,6 +354,7 @@ evaluatePackageBodyWith :: ( Evaluatable (Base term)
, Members '[ Fail
, Reader (Environment location value)
, State (Environment location value)
, Trace
] effects
, Recursive term
, termEffects ~ (LoopControl value ': Return value ': EvalClosure term value ': moduleEffects)

View File

@ -32,6 +32,7 @@ resolveGoImport :: Members '[ Reader ModuleInfo
, Reader (ModuleTable [Module term])
, Reader Package.PackageInfo
, Resumable ResolutionError
, Trace
] effects
=> ImportPath
-> Evaluator location term value effects [ModulePath]
@ -43,9 +44,9 @@ resolveGoImport (ImportPath path Relative) = do
_ -> pure paths
resolveGoImport (ImportPath path NonRelative) = do
package <- BC.unpack . unName . Package.packageName <$> currentPackage
traceM ("attempting to resolve " <> show path <> " for package " <> package)
traceE ("attempting to resolve " <> show path <> " for package " <> package)
case splitDirectories path of
-- Import an absolute path that's defined in this package being analyized.
-- Import an absolute path that's defined in this package being analyzed.
-- First two are source, next is package name, remaining are path to package
-- (e.g. github.com/golang/<package>/path...).
(_ : _ : p : xs) | p == package -> listModulesInDir (joinPath xs)
@ -65,7 +66,8 @@ instance Evaluatable Import where
eval (Import importPath _) = do
paths <- resolveGoImport importPath
for_ paths $ \path -> do
importedEnv <- maybe emptyEnv fst <$> traceResolve (unPath importPath) path (isolate (require path))
traceResolve (unPath importPath) path
importedEnv <- maybe emptyEnv fst <$> isolate (require path)
modifyEnv (mergeEnvs importedEnv)
unit
@ -86,9 +88,9 @@ instance Evaluatable QualifiedImport where
alias <- either (throwEvalError . FreeVariablesError) pure (freeVariable $ subterm aliasTerm)
void $ letrec' alias $ \addr -> do
for_ paths $ \path -> do
importedEnv <- maybe emptyEnv fst <$> traceResolve (unPath importPath) path (isolate (require path))
traceResolve (unPath importPath) path
importedEnv <- maybe emptyEnv fst <$> isolate (require path)
modifyEnv (mergeEnvs importedEnv)
makeNamespace alias addr Nothing
unit
@ -103,7 +105,8 @@ instance Show1 SideEffectImport where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable SideEffectImport where
eval (SideEffectImport importPath _) = do
paths <- resolveGoImport importPath
for_ paths $ \path -> traceResolve (unPath importPath) path $ isolate (require path)
traceResolve (unPath importPath) paths
for_ paths $ \path -> isolate (require path)
unit
-- A composite literal in Go

View File

@ -51,6 +51,7 @@ include :: ( AbstractValue location term value effects
, Resumable ResolutionError
, State (Environment location value)
, State (Exports location value)
, Trace
] effects
)
=> Subterm term (Evaluator location term value effects value)
@ -59,7 +60,8 @@ include :: ( AbstractValue location term value effects
include pathTerm f = do
name <- subtermValue pathTerm >>= asString
path <- resolvePHPName name
(importedEnv, v) <- traceResolve name path (isolate (f path)) >>= maybeM ((,) emptyEnv <$> unit)
traceResolve name path
(importedEnv, v) <- (isolate (f path)) >>= maybeM ((,) emptyEnv <$> unit)
modifyEnv (mergeEnvs importedEnv)
pure v

View File

@ -54,6 +54,7 @@ relativeQualifiedName prefix paths = RelativeQualifiedName (BC.unpack prefix) (J
resolvePythonModules :: Members '[ Reader ModuleInfo
, Reader (ModuleTable [Module term])
, Resumable ResolutionError
, Trace
] effects
=> QualifiedName
-> Evaluator location term value effects (NonEmpty ModulePath)
@ -61,7 +62,7 @@ resolvePythonModules q = do
relRootDir <- rootDir q <$> currentModule
for (moduleNames q) $ \name -> do
x <- search relRootDir name
traceResolve name x $ pure x
x <$ traceResolve name x
where
rootDir (QualifiedName _) ModuleInfo{..} = mempty -- overall rootDir of the Package.
rootDir (RelativeQualifiedName n _) ModuleInfo{..} = upDir numDots (takeDirectory modulePath)
@ -74,7 +75,7 @@ resolvePythonModules q = do
moduleNames (RelativeQualifiedName _ (Just paths)) = moduleNames paths
search rootDir x = do
traceM ("searching for " <> show x <> " in " <> show rootDir)
traceE ("searching for " <> show x <> " in " <> show rootDir)
let path = normalise (rootDir </> normalise x)
let searchPaths = [ path </> "__init__.py"
, path <.> ".py"

View File

@ -68,7 +68,8 @@ instance Evaluatable Require where
eval (Require _ x) = do
name <- subtermValue x >>= asString
path <- resolveRubyName name
(importedEnv, v) <- traceResolve name path (isolate (doRequire path))
traceResolve name path
(importedEnv, v) <- isolate (doRequire path)
modifyEnv (`mergeNewer` importedEnv)
pure v -- Returns True if the file was loaded, False if it was already loaded. http://ruby-doc.org/core-2.5.0/Kernel.html#method-i-require
@ -81,6 +82,7 @@ doRequire :: ( AbstractValue location term value effects
, State (Environment location value)
, State (Exports location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
)
=> M.ModulePath
@ -118,6 +120,7 @@ doLoad :: ( AbstractValue location term value effects
, State (Environment location value)
, State (Exports location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
)
=> ByteString
@ -125,7 +128,8 @@ doLoad :: ( AbstractValue location term value effects
-> Evaluator location term value effects value
doLoad path shouldWrap = do
path' <- resolveRubyPath path
importedEnv <- maybe emptyEnv fst <$> traceResolve path path' (isolate (load path'))
traceResolve path path'
importedEnv <- maybe emptyEnv fst <$> (isolate (load path'))
unless shouldWrap $ modifyEnv (mergeEnvs importedEnv)
boolean Prelude.True -- load always returns true. http://ruby-doc.org/core-2.5.0/Kernel.html#method-i-load

View File

@ -37,6 +37,7 @@ toName = FV.name . BC.pack . unPath
resolveWithNodejsStrategy :: Members '[ Reader M.ModuleInfo
, Reader (ModuleTable [M.Module term])
, Resumable ResolutionError
, Trace
] effects
=> ImportPath
-> [String]
@ -54,6 +55,7 @@ resolveWithNodejsStrategy (ImportPath path NonRelative) exts = resolveNonRelativ
resolveRelativePath :: Members '[ Reader M.ModuleInfo
, Reader (ModuleTable [M.Module term])
, Resumable ResolutionError
, Trace
] effects
=> FilePath
-> [String]
@ -62,7 +64,7 @@ resolveRelativePath relImportPath exts = do
M.ModuleInfo{..} <- currentModule
let relRootDir = takeDirectory modulePath
let path = joinPaths relRootDir relImportPath
resolveTSModule path exts >>= either notFound (\x -> traceResolve relImportPath x (pure x))
resolveTSModule path exts >>= either notFound (\x -> x <$ traceResolve relImportPath path)
where
notFound xs = throwResumable $ NotFoundError relImportPath xs Language.TypeScript
@ -79,6 +81,7 @@ resolveRelativePath relImportPath exts = do
resolveNonRelativePath :: Members '[ Reader M.ModuleInfo
, Reader (ModuleTable [M.Module term])
, Resumable ResolutionError
, Trace
] effects
=> FilePath
-> [String]
@ -94,7 +97,7 @@ resolveNonRelativePath name exts = do
case res of
Left xs | parentDir <- takeDirectory path , root /= parentDir -> go root parentDir (searched <> xs)
| otherwise -> notFound (searched <> xs)
Right m -> traceResolve name m $ pure m
Right m -> m <$ traceResolve name m
notFound xs = throwResumable $ NotFoundError name xs Language.TypeScript
resolveTSModule :: Members '[ Reader (ModuleTable [M.Module term]) ] effects
@ -126,6 +129,7 @@ evalRequire :: ( AbstractValue location term value effects
, State (Exports location value)
, State (Heap location value)
, State (ModuleTable (Environment location value, value))
, Trace
] effects
, Reducer value (Cell location value)
)

View File

@ -4,6 +4,7 @@ module Semantic.Graph where
import Analysis.Abstract.Evaluating
import Analysis.Abstract.Graph
import qualified Control.Exception as Exc
import Control.Monad.Effect (relayState, send)
import Data.Abstract.Address
import Data.Abstract.Evaluatable
import Data.Abstract.Located
@ -43,6 +44,7 @@ graph graphType renderer project
runGraphAnalysis
= run
. evaluating
. ignoringTraces
. resumingLoadError
. resumingUnspecialized
. resumingValueError
@ -55,6 +57,15 @@ graph graphType renderer project
constrainingTypes :: Evaluator (Located Precise) term (Value (Located Precise)) effects a -> Evaluator (Located Precise) term (Value (Located Precise)) effects a
constrainingTypes = id
ignoringTraces :: Effectful m => m (Trace ': effects) a -> m effects a
ignoringTraces = runEffect (\(Trace _) yield -> yield ())
printingTraces :: (Member IO effects, Effectful m) => m (Trace ': effects) a -> m effects a
printingTraces = raiseHandler (relay pure (\(Trace s) yield -> send (putStrLn s) >>= yield))
returningTraces :: (Functor (m effects), Effectful m) => m (Trace ': effects) a -> m effects (a, [String])
returningTraces e = fmap reverse <$> raiseHandler (relayState [] (\ts a -> pure (a, ts)) (\ts (Trace s) yield -> yield (s : ts) ())) e
-- | Parse a list of files into a 'Package'.
parsePackage :: Members '[Distribute WrappedTask, Files, Task] effs
=> Parser term -- ^ A parser.

View File

@ -6,6 +6,7 @@ import Analysis.Abstract.Caching
import Analysis.Abstract.Collecting
import Analysis.Abstract.Evaluating as X
import Control.Abstract.Evaluator
import Control.Monad.Effect (runM)
import Data.Abstract.Address
import Data.Abstract.Evaluatable
import Data.Abstract.Value
@ -25,8 +26,9 @@ import qualified Language.Python.Assignment as Python
import qualified Language.Ruby.Assignment as Ruby
justEvaluating
= run
= runM . lower
. evaluating
. printingTraces
. runLoadError
. runValueError
. runUnspecialized
@ -35,8 +37,9 @@ justEvaluating
. runAddressError
evaluatingWithHoles
= run
= runM . lower
. evaluating
. printingTraces
. resumingLoadError
. resumingUnspecialized
. resumingValueError
@ -46,8 +49,9 @@ evaluatingWithHoles
-- The order is significant here: caching has to run before typeChecking, or else well nondeterministically produce TypeErrors as part of the result set. While this is probably actually correct, it will require us to have an Ord instance for TypeError, which we dont have yet.
checking
= run
= runM . lower
. evaluating
. printingTraces
. providingLiveSet
. runLoadError
. runUnspecialized
@ -57,14 +61,14 @@ checking
. runTypeError
. caching @[]
evalGoProject path = justEvaluating <$> evaluateProject goParser Language.Go Nothing path
evalRubyProject path = justEvaluating <$> evaluateProject rubyParser Language.Ruby rubyPrelude path
evalPHPProject path = justEvaluating <$> evaluateProject phpParser Language.PHP Nothing path
evalPythonProject path = justEvaluating <$> evaluateProject pythonParser Language.Python pythonPrelude path
evalTypeScriptProjectQuietly path = evaluatingWithHoles <$> evaluateProject typescriptParser Language.TypeScript Nothing path
evalTypeScriptProject path = justEvaluating <$> evaluateProject typescriptParser Language.TypeScript Nothing path
evalGoProject path = justEvaluating =<< evaluateProject goParser Language.Go Nothing path
evalRubyProject path = justEvaluating =<< evaluateProject rubyParser Language.Ruby rubyPrelude path
evalPHPProject path = justEvaluating =<< evaluateProject phpParser Language.PHP Nothing path
evalPythonProject path = justEvaluating =<< evaluateProject pythonParser Language.Python pythonPrelude path
evalTypeScriptProjectQuietly path = evaluatingWithHoles =<< evaluateProject typescriptParser Language.TypeScript Nothing path
evalTypeScriptProject path = justEvaluating =<< evaluateProject typescriptParser Language.TypeScript Nothing path
typecheckGoFile path = checking <$> evaluateProjectWithCaching goParser Language.Go Nothing path
typecheckGoFile path = checking =<< evaluateProjectWithCaching goParser Language.Go Nothing path
rubyPrelude = Just $ File (TypeLevel.symbolVal (Proxy :: Proxy (PreludePath Ruby.Term))) (Just Language.Ruby)
pythonPrelude = Just $ File (TypeLevel.symbolVal (Proxy :: Proxy (PreludePath Python.Term))) (Just Language.Python)