mirror of
https://github.com/github/semantic.git
synced 2024-12-22 14:21:31 +03:00
Merge pull request #1691 from github/less-fail
Compute "holes" in the import graph
This commit is contained in:
commit
3e0c8a08d8
@ -15,7 +15,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.BadVariables
|
||||||
|
, Analysis.Abstract.Caching
|
||||||
, Analysis.Abstract.Collecting
|
, Analysis.Abstract.Collecting
|
||||||
, Analysis.Abstract.Dead
|
, Analysis.Abstract.Dead
|
||||||
, Analysis.Abstract.Evaluating
|
, Analysis.Abstract.Evaluating
|
||||||
|
31
src/Analysis/Abstract/BadVariables.hs
Normal file
31
src/Analysis/Abstract/BadVariables.hs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables, TypeApplications, TypeFamilies, TypeOperators #-}
|
||||||
|
module Analysis.Abstract.BadVariables where
|
||||||
|
|
||||||
|
import Control.Abstract.Analysis
|
||||||
|
import Data.Abstract.Evaluatable
|
||||||
|
import Prologue
|
||||||
|
|
||||||
|
-- An analysis that resumes from evaluation errors and records the list of unresolved free variables.
|
||||||
|
newtype BadVariables m term value (effects :: [* -> *]) a = BadVariables (m term value effects a)
|
||||||
|
deriving (Alternative, Applicative, Functor, Effectful, Monad, MonadFail, MonadFresh, MonadNonDet)
|
||||||
|
|
||||||
|
deriving instance MonadControl term (m term value effects) => MonadControl term (BadVariables m term value effects)
|
||||||
|
deriving instance MonadEnvironment value (m term value effects) => MonadEnvironment value (BadVariables m term value effects)
|
||||||
|
deriving instance MonadHeap value (m term value effects) => MonadHeap value (BadVariables m term value effects)
|
||||||
|
deriving instance MonadModuleTable term value (m term value effects) => MonadModuleTable term value (BadVariables m term value effects)
|
||||||
|
deriving instance MonadEvaluator term value (m term value effects) => MonadEvaluator term value (BadVariables m term value effects)
|
||||||
|
|
||||||
|
instance ( Effectful (m term value)
|
||||||
|
, Member (Resumable (EvalError value)) effects
|
||||||
|
, Member (State [Name]) effects
|
||||||
|
, MonadAnalysis term value (m term value effects)
|
||||||
|
, MonadValue value (BadVariables m term value effects)
|
||||||
|
)
|
||||||
|
=> MonadAnalysis term value (BadVariables m term value effects) where
|
||||||
|
type RequiredEffects term value (BadVariables m term value effects) = State [Name] ': RequiredEffects term value (m term value effects)
|
||||||
|
|
||||||
|
analyzeTerm eval term = resumeException @(EvalError value) (liftAnalyze analyzeTerm eval term) (
|
||||||
|
\yield (FreeVariableError name) ->
|
||||||
|
raise (modify (name :)) >> unit >>= yield)
|
||||||
|
|
||||||
|
analyzeModule = liftAnalyze analyzeModule
|
@ -27,7 +27,9 @@ deriving instance Member NonDet effects => MonadNonDet (Evaluating term value
|
|||||||
|
|
||||||
-- | Effects necessary for evaluating (whether concrete or abstract).
|
-- | Effects necessary for evaluating (whether concrete or abstract).
|
||||||
type EvaluatingEffects term value
|
type EvaluatingEffects term value
|
||||||
= '[ Resumable (ValueExc value)
|
= '[ Resumable (EvalError value)
|
||||||
|
, Resumable (LoadError term value)
|
||||||
|
, Resumable (ValueExc value)
|
||||||
, Resumable (Unspecialized value)
|
, Resumable (Unspecialized value)
|
||||||
, Fail -- Failure with an error message
|
, Fail -- Failure with an error message
|
||||||
, Reader [Module term] -- The stack of currently-evaluating modules.
|
, Reader [Module term] -- The stack of currently-evaluating modules.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, ScopedTypeVariables, StandaloneDeriving,
|
||||||
|
TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Analysis.Abstract.ImportGraph
|
module Analysis.Abstract.ImportGraph
|
||||||
( ImportGraph(..)
|
( ImportGraph(..)
|
||||||
, renderImportGraph
|
, renderImportGraph
|
||||||
@ -9,6 +10,7 @@ import qualified Algebra.Graph as G
|
|||||||
import Algebra.Graph.Class
|
import Algebra.Graph.Class
|
||||||
import Algebra.Graph.Export.Dot
|
import Algebra.Graph.Export.Dot
|
||||||
import Control.Abstract.Analysis
|
import Control.Abstract.Analysis
|
||||||
|
import Data.Abstract.Evaluatable (LoadError (..))
|
||||||
import Data.Abstract.FreeVariables
|
import Data.Abstract.FreeVariables
|
||||||
import Data.Abstract.Module
|
import Data.Abstract.Module
|
||||||
import Prologue hiding (empty)
|
import Prologue hiding (empty)
|
||||||
@ -34,17 +36,29 @@ deriving instance MonadEvaluator term value (m term value effects) => MonadEvalu
|
|||||||
instance ( Effectful (m term value)
|
instance ( Effectful (m term value)
|
||||||
, Member (State ImportGraph) effects
|
, Member (State ImportGraph) effects
|
||||||
, MonadAnalysis term value (m term value effects)
|
, MonadAnalysis term value (m term value effects)
|
||||||
|
, Member (Resumable (LoadError term value)) effects
|
||||||
)
|
)
|
||||||
=> MonadAnalysis term value (ImportGraphing m term value effects) where
|
=> MonadAnalysis term value (ImportGraphing m term value effects) where
|
||||||
type RequiredEffects term value (ImportGraphing m term value effects) = State ImportGraph ': RequiredEffects term value (m term value effects)
|
type RequiredEffects term value (ImportGraphing m term value effects) = State ImportGraph ': RequiredEffects term value (m term value effects)
|
||||||
|
|
||||||
analyzeTerm = liftAnalyze analyzeTerm
|
analyzeTerm eval term = resumeException
|
||||||
|
@(LoadError term value)
|
||||||
|
(liftAnalyze analyzeTerm eval term)
|
||||||
|
(\yield (LoadError name) -> insertVertexName name >> yield [])
|
||||||
|
|
||||||
analyzeModule recur m = do
|
analyzeModule recur m = do
|
||||||
|
insertVertexName (moduleName m)
|
||||||
|
liftAnalyze analyzeModule recur m
|
||||||
|
|
||||||
|
insertVertexName :: (Effectful (m term value)
|
||||||
|
, Member (State ImportGraph) effects
|
||||||
|
, MonadEvaluator term value (m term value effects))
|
||||||
|
=> NonEmpty ByteString
|
||||||
|
-> ImportGraphing m term value effects ()
|
||||||
|
insertVertexName name = do
|
||||||
ms <- askModuleStack
|
ms <- askModuleStack
|
||||||
let parent = maybe empty (vertex . moduleName) (listToMaybe ms)
|
let parent = maybe empty (vertex . moduleName) (listToMaybe ms)
|
||||||
modifyImportGraph (parent >< vertex (moduleName m) <>)
|
modifyImportGraph (parent >< vertex name <>)
|
||||||
liftAnalyze analyzeModule recur m
|
|
||||||
|
|
||||||
(><) :: Graph a => a -> a -> a
|
(><) :: Graph a => a -> a -> a
|
||||||
(><) = connect
|
(><) = connect
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
module Analysis.Abstract.Quiet where
|
module Analysis.Abstract.Quiet where
|
||||||
|
|
||||||
import Control.Abstract.Analysis
|
import Control.Abstract.Analysis
|
||||||
import Control.Monad.Effect.Resumable
|
|
||||||
import Data.Abstract.Evaluatable
|
import Data.Abstract.Evaluatable
|
||||||
import Prologue
|
import Prologue
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import qualified Control.Monad.Effect as Effect
|
|||||||
import Control.Monad.Effect.Fail as X
|
import Control.Monad.Effect.Fail as X
|
||||||
import Control.Monad.Effect.Reader as X
|
import Control.Monad.Effect.Reader as X
|
||||||
import Control.Monad.Effect.State as X
|
import Control.Monad.Effect.State as X
|
||||||
|
import Control.Monad.Effect.Resumable as X
|
||||||
import Data.Abstract.Module
|
import Data.Abstract.Module
|
||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
import Data.Type.Coercion
|
import Data.Type.Coercion
|
||||||
|
@ -26,7 +26,7 @@ import Data.Abstract.Number as Number
|
|||||||
import Data.Scientific (Scientific)
|
import Data.Scientific (Scientific)
|
||||||
import Data.Semigroup.Reducer hiding (unit)
|
import Data.Semigroup.Reducer hiding (unit)
|
||||||
import Prelude
|
import Prelude
|
||||||
import Prologue
|
import Prologue hiding (TypeError)
|
||||||
|
|
||||||
-- | This datum is passed into liftComparison to handle the fact that Ruby and PHP
|
-- | This datum is passed into liftComparison to handle the fact that Ruby and PHP
|
||||||
-- have built-in generalized-comparison ("spaceship") operators. If you want to
|
-- have built-in generalized-comparison ("spaceship") operators. If you want to
|
||||||
@ -196,12 +196,16 @@ class ValueRoots value where
|
|||||||
|
|
||||||
-- The type of exceptions that can be thrown when constructing values in `MonadValue`.
|
-- The type of exceptions that can be thrown when constructing values in `MonadValue`.
|
||||||
data ValueExc value resume where
|
data ValueExc value resume where
|
||||||
ValueExc :: Prelude.String -> ValueExc value value
|
TypeError :: Prelude.String -> ValueExc value value
|
||||||
StringExc :: Prelude.String -> ValueExc value ByteString
|
StringError :: Prelude.String -> ValueExc value ByteString
|
||||||
|
NamespaceError :: Prelude.String -> ValueExc value (EnvironmentFor value)
|
||||||
|
ScopedEnvironmentError :: Prelude.String -> ValueExc value (EnvironmentFor value)
|
||||||
|
|
||||||
instance Eq1 (ValueExc value) where
|
instance Eq1 (ValueExc value) where
|
||||||
liftEq _ (ValueExc a) (ValueExc b) = a == b
|
liftEq _ (TypeError a) (TypeError b) = a == b
|
||||||
liftEq _ (StringExc a) (StringExc b) = a == b
|
liftEq _ (StringError a) (StringError b) = a == b
|
||||||
|
liftEq _ (NamespaceError a) (NamespaceError b) = a == b
|
||||||
|
liftEq _ (ScopedEnvironmentError a) (ScopedEnvironmentError b) = a == b
|
||||||
liftEq _ _ _ = False
|
liftEq _ _ _ = False
|
||||||
|
|
||||||
deriving instance Show (ValueExc value resume)
|
deriving instance Show (ValueExc value resume)
|
||||||
|
@ -4,10 +4,13 @@ module Data.Abstract.Evaluatable
|
|||||||
, MonadEvaluatable
|
, MonadEvaluatable
|
||||||
, Evaluatable(..)
|
, Evaluatable(..)
|
||||||
, Unspecialized(..)
|
, Unspecialized(..)
|
||||||
|
, LoadError(..)
|
||||||
|
, EvalError(..)
|
||||||
, evaluateTerm
|
, evaluateTerm
|
||||||
, evaluateModule
|
, evaluateModule
|
||||||
, withModules
|
, withModules
|
||||||
, evaluateModules
|
, evaluateModules
|
||||||
|
, throwLoadError
|
||||||
, require
|
, require
|
||||||
, load
|
, load
|
||||||
) where
|
) where
|
||||||
@ -31,11 +34,41 @@ type MonadEvaluatable term value m =
|
|||||||
, MonadAddressable (LocationFor value) value m
|
, MonadAddressable (LocationFor value) value m
|
||||||
, MonadAnalysis term value m
|
, MonadAnalysis term value m
|
||||||
, MonadThrow (Unspecialized value) m
|
, MonadThrow (Unspecialized value) m
|
||||||
|
, MonadThrow (ValueExc value) m
|
||||||
|
, MonadThrow (LoadError term value) m
|
||||||
|
, MonadThrow (EvalError value) m
|
||||||
, MonadValue value m
|
, MonadValue value m
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Show (LocationFor value)
|
, Show (LocationFor value)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
-- | 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.
|
||||||
|
data LoadError term value resume where
|
||||||
|
LoadError :: ModuleName -> LoadError term value [Module term]
|
||||||
|
|
||||||
|
deriving instance Eq (LoadError term a b)
|
||||||
|
deriving instance Show (LoadError term a b)
|
||||||
|
instance Show1 (LoadError term value) where
|
||||||
|
liftShowsPrec _ _ = showsPrec
|
||||||
|
instance Eq1 (LoadError term a) where
|
||||||
|
liftEq _ (LoadError a) (LoadError b) = a == b
|
||||||
|
|
||||||
|
-- | The type of error thrown when failing to evaluate a term.
|
||||||
|
data EvalError value resume where
|
||||||
|
-- Indicates we weren't able to dereference a name from the evaluated environment.
|
||||||
|
FreeVariableError :: Name -> EvalError value value
|
||||||
|
|
||||||
|
deriving instance Eq (EvalError a b)
|
||||||
|
deriving instance Show (EvalError a b)
|
||||||
|
instance Show1 (EvalError value) where
|
||||||
|
liftShowsPrec _ _ = showsPrec
|
||||||
|
instance Eq1 (EvalError term) where
|
||||||
|
liftEq _ (FreeVariableError a) (FreeVariableError b) = a == b
|
||||||
|
|
||||||
|
throwLoadError :: MonadEvaluatable term value m => LoadError term value resume -> m resume
|
||||||
|
throwLoadError = throwException
|
||||||
|
|
||||||
data Unspecialized a b where
|
data Unspecialized a b where
|
||||||
Unspecialized :: { getUnspecialized :: Prelude.String } -> Unspecialized value value
|
Unspecialized :: { getUnspecialized :: Prelude.String } -> Unspecialized value value
|
||||||
|
|
||||||
@ -88,9 +121,9 @@ require name = getModuleTable >>= maybe (load name) pure . moduleTableLookup nam
|
|||||||
load :: MonadEvaluatable term value m
|
load :: MonadEvaluatable term value m
|
||||||
=> ModuleName
|
=> ModuleName
|
||||||
-> m (EnvironmentFor value, value)
|
-> m (EnvironmentFor value, value)
|
||||||
load name = askModuleTable >>= maybe notFound evalAndCache . moduleTableLookup name
|
load name = askModuleTable >>= maybe notFound pure . moduleTableLookup name >>= evalAndCache
|
||||||
where
|
where
|
||||||
notFound = fail ("cannot load module: " <> show name)
|
notFound = throwLoadError (LoadError name)
|
||||||
|
|
||||||
evalAndCache [] = (,) <$> pure mempty <*> unit
|
evalAndCache [] = (,) <$> pure mempty <*> unit
|
||||||
evalAndCache [x] = evalAndCache' x
|
evalAndCache [x] = evalAndCache' x
|
||||||
|
@ -9,7 +9,7 @@ import Data.Abstract.Evaluatable
|
|||||||
import qualified Data.Abstract.Number as Number
|
import qualified Data.Abstract.Number as Number
|
||||||
import Data.Scientific (Scientific)
|
import Data.Scientific (Scientific)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Prologue
|
import Prologue hiding (TypeError)
|
||||||
import Prelude hiding (Float, Integer, String, Rational, fail)
|
import Prelude hiding (Float, Integer, String, Rational, fail)
|
||||||
import qualified Prelude
|
import qualified Prelude
|
||||||
|
|
||||||
@ -225,12 +225,12 @@ instance (Monad m, MonadEvaluatable term Value m) => MonadValue Value m where
|
|||||||
pure (injValue (Namespace n (Env.mergeNewer env' env)))
|
pure (injValue (Namespace n (Env.mergeNewer env' env)))
|
||||||
where asNamespaceEnv v
|
where asNamespaceEnv v
|
||||||
| Just (Namespace _ env') <- prjValue v = pure env'
|
| Just (Namespace _ env') <- prjValue v = pure env'
|
||||||
| otherwise = fail ("expected " <> show v <> " to be a namespace")
|
| otherwise = throwException $ NamespaceError ("expected " <> show v <> " to be a namespace")
|
||||||
|
|
||||||
scopedEnvironment o
|
scopedEnvironment o
|
||||||
| Just (Class _ env) <- prjValue o = pure env
|
| Just (Class _ env) <- prjValue o = pure env
|
||||||
| Just (Namespace _ env) <- prjValue o = pure env
|
| Just (Namespace _ env) <- prjValue o = pure env
|
||||||
| otherwise = fail ("object type passed to scopedEnvironment doesn't have an environment: " <> show o)
|
| otherwise = throwException $ ScopedEnvironmentError ("object type passed to scopedEnvironment doesn't have an environment: " <> show o)
|
||||||
|
|
||||||
asString v
|
asString v
|
||||||
| Just (String n) <- prjValue v = pure n
|
| Just (String n) <- prjValue v = pure n
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
{-# OPTIONS_GHC -Wno-redundant-constraints #-} -- For HasCallStack
|
{-# OPTIONS_GHC -Wno-redundant-constraints #-} -- For HasCallStack
|
||||||
module Data.Syntax where
|
module Data.Syntax where
|
||||||
|
|
||||||
import Control.Monad.Fail
|
import Data.Abstract.Evaluatable hiding (catchError)
|
||||||
import Data.Abstract.Evaluatable
|
|
||||||
import Data.AST
|
import Data.AST
|
||||||
import Data.Range
|
import Data.Range
|
||||||
import Data.Record
|
import Data.Record
|
||||||
import Data.Span
|
import Data.Span
|
||||||
import Data.Term
|
import Data.Term
|
||||||
import Diffing.Algorithm hiding (Empty)
|
import Diffing.Algorithm hiding (Empty)
|
||||||
import Prelude hiding (fail)
|
import Prelude
|
||||||
import Prologue
|
import Prologue
|
||||||
import qualified Assigning.Assignment as Assignment
|
import qualified Assigning.Assignment as Assignment
|
||||||
import qualified Data.Error as Error
|
import qualified Data.Error as Error
|
||||||
@ -107,7 +106,7 @@ instance Ord1 Identifier where liftCompare = genericLiftCompare
|
|||||||
instance Show1 Identifier where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Identifier where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
instance Evaluatable Identifier where
|
instance Evaluatable Identifier where
|
||||||
eval (Identifier name) = lookupWith deref name >>= maybe (fail ("free variable: " <> show (friendlyName name))) pure
|
eval (Identifier name) = lookupWith deref name >>= maybe (throwException $ FreeVariableError name) pure
|
||||||
|
|
||||||
instance FreeVariables1 Identifier where
|
instance FreeVariables1 Identifier where
|
||||||
liftFreeVariables _ (Identifier x) = pure x
|
liftFreeVariables _ (Identifier x) = pure x
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
{-# OPTIONS_GHC -Wno-missing-signatures #-}
|
{-# OPTIONS_GHC -Wno-missing-signatures #-}
|
||||||
module Semantic.Util where
|
module Semantic.Util where
|
||||||
|
|
||||||
|
import Analysis.Abstract.BadVariables
|
||||||
import Analysis.Abstract.Caching
|
import Analysis.Abstract.Caching
|
||||||
import Analysis.Abstract.Dead
|
import Analysis.Abstract.Dead
|
||||||
import Analysis.Abstract.Evaluating as X
|
import Analysis.Abstract.Evaluating as X
|
||||||
|
import Analysis.Abstract.ImportGraph
|
||||||
import Analysis.Abstract.Tracing
|
import Analysis.Abstract.Tracing
|
||||||
import Analysis.Declaration
|
import Analysis.Declaration
|
||||||
import Control.Abstract.Analysis
|
import Control.Abstract.Analysis
|
||||||
@ -34,11 +36,14 @@ import System.FilePath.Posix
|
|||||||
|
|
||||||
import qualified Language.Go.Assignment as Go
|
import qualified Language.Go.Assignment as Go
|
||||||
import qualified Language.Python.Assignment as Python
|
import qualified Language.Python.Assignment as Python
|
||||||
|
import qualified Language.Ruby.Assignment as Ruby
|
||||||
import qualified Language.TypeScript.Assignment as TypeScript
|
import qualified Language.TypeScript.Assignment as TypeScript
|
||||||
|
|
||||||
-- Ruby
|
-- Ruby
|
||||||
evaluateRubyFile = evaluateWithPrelude rubyParser
|
evaluateRubyFile = evaluateWithPrelude rubyParser
|
||||||
evaluateRubyFiles = evaluateFilesWithPrelude rubyParser
|
evaluateRubyFiles = evaluateFilesWithPrelude rubyParser
|
||||||
|
evaluateRubyImportGraph paths = runAnalysis @(ImportGraphing Evaluating Ruby.Term Value) . evaluateModules <$> parseFiles rubyParser paths
|
||||||
|
evaluateRubyBadVariables paths = runAnalysis @(BadVariables Evaluating Ruby.Term Value) . evaluateModules <$> parseFiles rubyParser paths
|
||||||
|
|
||||||
-- Go
|
-- Go
|
||||||
evaluateGoFile = evaluateFile goParser
|
evaluateGoFile = evaluateFile goParser
|
||||||
|
@ -30,11 +30,11 @@ spec = parallel $ do
|
|||||||
|
|
||||||
it "subclasses" $ do
|
it "subclasses" $ do
|
||||||
v <- fst <$> evaluate "subclass.py"
|
v <- fst <$> evaluate "subclass.py"
|
||||||
v `shouldBe` Right (Right (Right (injValue (String "\"bar\""))))
|
v `shouldBe` Right (Right (Right (Right (Right (injValue (String "\"bar\""))))))
|
||||||
|
|
||||||
it "handles multiple inheritance left-to-right" $ do
|
it "handles multiple inheritance left-to-right" $ do
|
||||||
v <- fst <$> evaluate "multiple_inheritance.py"
|
v <- fst <$> evaluate "multiple_inheritance.py"
|
||||||
v `shouldBe` Right (Right (Right (injValue (String "\"foo!\""))))
|
v `shouldBe` Right (Right (Right (Right (Right (injValue (String "\"foo!\""))))))
|
||||||
|
|
||||||
where
|
where
|
||||||
addr = Address . Precise
|
addr = Address . Precise
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
module Analysis.Ruby.Spec (spec) where
|
module Analysis.Ruby.Spec (spec) where
|
||||||
|
|
||||||
|
import Data.Abstract.Evaluatable (EvalError(..))
|
||||||
import Data.Abstract.Value
|
import Data.Abstract.Value
|
||||||
|
import Control.Monad.Effect (SomeExc(..))
|
||||||
|
import Data.List.NonEmpty (NonEmpty(..))
|
||||||
import Data.Map
|
import Data.Map
|
||||||
import Data.Map.Monoidal as Map
|
import Data.Map.Monoidal as Map
|
||||||
|
|
||||||
@ -24,12 +27,12 @@ spec = parallel $ do
|
|||||||
|
|
||||||
it "evaluates load with wrapper" $ do
|
it "evaluates load with wrapper" $ do
|
||||||
res <- evaluate "load-wrap.rb"
|
res <- evaluate "load-wrap.rb"
|
||||||
fst res `shouldBe` Left "free variable: \"foo\""
|
fst res `shouldBe` Right (Right (Right (Right (Left (SomeExc (FreeVariableError ("foo" :| [])))))))
|
||||||
environment (snd res) `shouldBe` [ (name "Object", addr 0) ]
|
environment (snd res) `shouldBe` [ (name "Object", addr 0) ]
|
||||||
|
|
||||||
it "evaluates subclass" $ do
|
it "evaluates subclass" $ do
|
||||||
res <- evaluate "subclass.rb"
|
res <- evaluate "subclass.rb"
|
||||||
fst res `shouldBe` Right (Right (Right (injValue (String "\"<bar>\""))))
|
fst res `shouldBe` Right (Right (Right (Right (Right (injValue (String "\"<bar>\""))))))
|
||||||
environment (snd res) `shouldBe` [ (name "Bar", addr 6)
|
environment (snd res) `shouldBe` [ (name "Bar", addr 6)
|
||||||
, (name "Foo", addr 3)
|
, (name "Foo", addr 3)
|
||||||
, (name "Object", addr 0) ]
|
, (name "Object", addr 0) ]
|
||||||
@ -41,13 +44,13 @@ spec = parallel $ do
|
|||||||
|
|
||||||
it "evaluates modules" $ do
|
it "evaluates modules" $ do
|
||||||
res <- evaluate "modules.rb"
|
res <- evaluate "modules.rb"
|
||||||
fst res `shouldBe` Right (Right (Right (injValue (String "\"<hello>\""))))
|
fst res `shouldBe` Right (Right (Right (Right (Right (injValue (String "\"<hello>\""))))))
|
||||||
environment (snd res) `shouldBe` [ (name "Object", addr 0)
|
environment (snd res) `shouldBe` [ (name "Object", addr 0)
|
||||||
, (name "Bar", addr 3) ]
|
, (name "Bar", addr 3) ]
|
||||||
|
|
||||||
it "has prelude" $ do
|
it "has prelude" $ do
|
||||||
res <- fst <$> evaluate "preluded.rb"
|
res <- fst <$> evaluate "preluded.rb"
|
||||||
res `shouldBe` Right (Right (Right (injValue (String "\"<foo>\""))))
|
res `shouldBe` Right (Right (Right (Right (Right (injValue (String "\"<foo>\""))))))
|
||||||
|
|
||||||
where
|
where
|
||||||
ns n = Just . Latest . Just . injValue . Namespace (name n)
|
ns n = Just . Latest . Just . injValue . Namespace (name n)
|
||||||
|
3
test/fixtures/ruby/analysis/src/foo.rb
vendored
Normal file
3
test/fixtures/ruby/analysis/src/foo.rb
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
def foo()
|
||||||
|
return "in foo"
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user