1
1
mirror of https://github.com/github/semantic.git synced 2024-12-24 07:25:44 +03:00

Merge branch 'master' into gorzell-container

This commit is contained in:
Greg Orzell 2018-03-19 10:52:47 +01:00 committed by GitHub
commit 02fbc3b22c
61 changed files with 1109 additions and 557 deletions

View File

@ -51,6 +51,7 @@ library
, Data.Abstract.Live
, Data.Abstract.ModuleTable
, Data.Abstract.Number
, Data.Abstract.Path
, Data.Abstract.Type
, Data.Abstract.Value
-- General datatype definitions & generic algorithms
@ -99,6 +100,7 @@ library
, Language.JSON.Assignment
, Language.Ruby.Grammar
, Language.Ruby.Assignment
, Language.Ruby.Syntax
, Language.TypeScript.Assignment
, Language.TypeScript.Grammar
, Language.TypeScript.Syntax
@ -208,6 +210,7 @@ test-suite test
other-modules: Assigning.Assignment.Spec
, Analysis.Go.Spec
, Analysis.Python.Spec
, Analysis.Ruby.Spec
, Analysis.TypeScript.Spec
, Data.Diff.Spec
, Data.Functor.Classes.Generic.Spec

View File

@ -14,7 +14,6 @@ import Control.Monad.Effect.Reader
import Control.Monad.Effect.State
import Data.Abstract.Configuration
import Data.Abstract.Evaluatable
import Data.Abstract.Address
import Data.Abstract.ModuleTable
import Data.Abstract.Value
import Data.Blob
@ -81,12 +80,11 @@ type EvaluatingEffects term value
= '[ Fail -- Failure with an error message
, Reader (EnvironmentFor value) -- Local environment (e.g. binding over a closure)
, State (EnvironmentFor value) -- Global (imperative) environment
, State (HeapFor value) -- The heap
, State (HeapFor value) -- The heap
, Reader (ModuleTable [term]) -- Cache of unevaluated modules
, State (ModuleTable (EnvironmentFor value)) -- Cache of evaluated modules
, State (Map Name (Name, Maybe (Address (LocationFor value) value))) -- Set of exports
, State (IntMap.IntMap term) -- For jumps
, State (ExportsFor value) -- Exports (used to filter environments when they are imported)
, State (IntMap.IntMap term) -- For jumps
]
instance Members '[Fail, State (IntMap.IntMap term)] effects => MonadControl term (Evaluating term value effects) where
@ -98,13 +96,13 @@ instance Members '[Fail, State (IntMap.IntMap term)] effects => MonadControl ter
goto label = IntMap.lookup label <$> raise get >>= maybe (fail ("unknown label: " <> show label)) pure
instance Members '[State (Map Name (Name, Maybe (Address (LocationFor value) value))), Reader (EnvironmentFor value), State (EnvironmentFor value)] effects => MonadEnvironment value (Evaluating term value effects) where
instance Members '[State (ExportsFor value), Reader (EnvironmentFor value), State (EnvironmentFor value)] effects => MonadEnvironment value (Evaluating term value effects) where
getGlobalEnv = raise get
putGlobalEnv = raise . put
withGlobalEnv s = raise . localState s . lower
addExport key = raise . modify . Map.insert key
getExports = raise get
putExports = raise . put
withExports s = raise . localState s . lower
askLocalEnv = raise ask

View File

@ -18,6 +18,7 @@ import Data.Abstract.FreeVariables
import qualified Data.Syntax as Syntax
import qualified Data.Syntax.Declaration as Declaration
import qualified Data.Syntax.Expression as Expression
import qualified Language.Ruby.Syntax as Ruby.Syntax
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Language.Markdown.Syntax as Markdown
@ -98,54 +99,59 @@ instance CustomHasDeclaration whole Declaration.Function where
-- Do not summarize anonymous functions
| isEmpty identifierAnn = Nothing
-- Named functions
| otherwise = Just $ FunctionDeclaration (getSource identifierAnn) (getFunctionSource blob (In ann decl)) blobLanguage
where getSource = toText . flip Source.slice blobSource . getField
isEmpty = (== 0) . rangeLength . getField
| otherwise = Just $ FunctionDeclaration (getSource blobSource identifierAnn) (getFunctionSource blob (In ann decl)) blobLanguage
where isEmpty = (== 0) . rangeLength . getField
-- | Produce a 'MethodDeclaration' for 'Declaration.Method' nodes. If the methods receiver is non-empty (defined as having a non-empty 'Range'), the 'declarationIdentifier' will be formatted as 'receiver.method_name'; otherwise it will be simply 'method_name'.
instance CustomHasDeclaration whole Declaration.Method where
customToDeclaration blob@Blob{..} ann decl@(Declaration.Method _ (Term (In receiverAnn receiverF), _) (Term (In identifierAnn _), _) _ _)
-- Methods without a receiver
| isEmpty receiverAnn = Just $ MethodDeclaration (getSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage Nothing
| isEmpty receiverAnn = Just $ MethodDeclaration (getSource blobSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage Nothing
-- Methods with a receiver type and an identifier (e.g. (a *Type) in Go).
| blobLanguage == Just Go
, [ _, Term (In receiverType _) ] <- toList receiverF = Just $ MethodDeclaration (getSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage (Just (getSource receiverType))
, [ _, Term (In receiverType _) ] <- toList receiverF = Just $ MethodDeclaration (getSource blobSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage (Just (getSource blobSource receiverType))
-- Methods with a receiver (class methods) are formatted like `receiver.method_name`
| otherwise = Just $ MethodDeclaration (getSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage (Just (getSource receiverAnn))
where getSource = toText . flip Source.slice blobSource . getField
isEmpty = (== 0) . rangeLength . getField
| otherwise = Just $ MethodDeclaration (getSource blobSource identifierAnn) (getMethodSource blob (In ann decl)) blobLanguage (Just (getSource blobSource receiverAnn))
where isEmpty = (== 0) . rangeLength . getField
-- | Produce a 'ClassDeclaration' for 'Declaration.Class' nodes.
instance CustomHasDeclaration whole Declaration.Class where
customToDeclaration blob@Blob{..} ann decl@(Declaration.Class _ (Term (In identifierAnn _), _) _ _)
-- Classes
= Just $ ClassDeclaration (getSource identifierAnn) (getClassSource blob (In ann decl)) blobLanguage
where getSource = toText . flip Source.slice blobSource . getField
= Just $ ClassDeclaration (getSource blobSource identifierAnn) (getClassSource blob (In ann decl)) blobLanguage
instance CustomHasDeclaration (Union fs) Declaration.Import where
customToDeclaration Blob{..} _ (Declaration.Import (Term (In fromAnn _), _) symbols)
= Just $ ImportDeclaration ((stripQuotes . getSource) fromAnn) "" (fmap getSymbol symbols) blobLanguage
customToDeclaration Blob{..} _ (Declaration.Import (Term (In fromAnn _), _) symbols _)
= Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromAnn) "" (fmap getSymbol symbols) blobLanguage
where
stripQuotes = T.dropAround (`elem` ['"', '\''])
getSource = toText . flip Source.slice blobSource . getField
getSymbol = let f = (T.decodeUtf8 . friendlyName) in bimap f f
instance (Syntax.Identifier :< fs) => CustomHasDeclaration (Union fs) Declaration.QualifiedImport where
customToDeclaration Blob{..} _ (Declaration.QualifiedImport (Term (In fromAnn _), _) (Term (In aliasAnn aliasF), _) symbols)
| Just (Syntax.Identifier alias) <- prj aliasF = Just $ ImportDeclaration ((stripQuotes . getSource) fromAnn) (toName alias) (fmap getSymbol symbols) blobLanguage
| otherwise = Just $ ImportDeclaration ((stripQuotes . getSource) fromAnn) (getSource aliasAnn) (fmap getSymbol symbols) blobLanguage
| Just (Syntax.Identifier alias) <- prj aliasF = Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromAnn) (toName alias) (fmap getSymbol symbols) blobLanguage
| otherwise = Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromAnn) (getSource blobSource aliasAnn) (fmap getSymbol symbols) blobLanguage
where
stripQuotes = T.dropAround (`elem` ['"', '\''])
getSource = toText . flip Source.slice blobSource . getField
getSymbol = bimap toName toName
toName = T.decodeUtf8 . friendlyName
instance CustomHasDeclaration (Union fs) Declaration.WildcardImport where
customToDeclaration Blob{..} _ (Declaration.WildcardImport (Term (In fromAnn _), _) _)
= Just $ ImportDeclaration ((stripQuotes . getSource) fromAnn) "" [] blobLanguage
where
stripQuotes = T.dropAround (`elem` ['"', '\''])
getSource = toText . flip Source.slice blobSource . getField
instance CustomHasDeclaration (Union fs) Declaration.SideEffectImport where
customToDeclaration Blob{..} _ (Declaration.SideEffectImport (Term (In fromAnn _), _) _)
= Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromAnn) "" [] blobLanguage
instance CustomHasDeclaration (Union fs) Ruby.Syntax.Require where
customToDeclaration Blob{..} _ (Ruby.Syntax.Require _ (Term (In fromAnn _), _))
= Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromAnn) "" [] blobLanguage
instance CustomHasDeclaration (Union fs) Ruby.Syntax.Load where
customToDeclaration Blob{..} _ (Ruby.Syntax.Load ((Term (In fromArgs _), _):_))
= Just $ ImportDeclaration ((stripQuotes . getSource blobSource) fromArgs) "" [] blobLanguage
customToDeclaration Blob{..} _ (Ruby.Syntax.Load _)
= Nothing
getSource :: HasField fields Range => Source -> Record fields -> Text
getSource blobSource = toText . flip Source.slice blobSource . getField
stripQuotes :: Text -> Text
stripQuotes = T.dropAround (`elem` ['"', '\''])
instance (Syntax.Identifier :< fs, Expression.MemberAccess :< fs) => CustomHasDeclaration (Union fs) Expression.Call where
customToDeclaration Blob{..} _ (Expression.Call _ (Term (In fromAnn fromF), _) _ _)
@ -184,7 +190,8 @@ type family DeclarationStrategy syntax where
DeclarationStrategy Declaration.Function = 'Custom
DeclarationStrategy Declaration.Import = 'Custom
DeclarationStrategy Declaration.QualifiedImport = 'Custom
DeclarationStrategy Declaration.WildcardImport = 'Custom
DeclarationStrategy Declaration.SideEffectImport = 'Custom
DeclarationStrategy Ruby.Syntax.Require = 'Custom
DeclarationStrategy Declaration.Method = 'Custom
DeclarationStrategy Markdown.Heading = 'Custom
DeclarationStrategy Expression.Call = 'Custom

View File

@ -41,6 +41,10 @@ class (MonadEvaluator term value m, Recursive term) => MonadAnalysis term value
evaluateModule :: term -> m value
evaluateModule = evaluateTerm
-- | Isolate the given action with an empty global environment and exports.
isolate :: m a -> m a
isolate = withGlobalEnv mempty . withExports mempty
-- | Evaluate a term to a value using the semantics of the current analysis.
--
-- This should always be called when e.g. evaluating the bodies of closures instead of explicitly folding either 'eval' or 'analyzeTerm' over subterms, except in 'MonadAnalysis' instances themselves. On the other hand, top-level evaluation should be performed using 'evaluateModule'.
@ -67,19 +71,25 @@ load :: ( MonadAnalysis term value m
=> ModuleName
-> m (EnvironmentFor value)
load name = askModuleTable >>= maybe notFound evalAndCache . moduleTableLookup name
where notFound = fail ("cannot load module: " <> show name)
evalAndCache :: (MonadAnalysis term value m, Ord (LocationFor value)) => [term] -> m (EnvironmentFor value)
evalAndCache [] = pure mempty
evalAndCache (x:xs) = do
void $ evaluateModule x
env <- getGlobalEnv
exports <- getExports
-- TODO: If the set of exports is empty because no exports have been
-- defined, do we export all terms, or no terms? This behavior varies across
-- languages. We need better semantics rather than doing it ad-hoc.
let env' = if Map.null exports then env else bindExports exports env
modifyModuleTable (moduleTableInsert name env')
(env' <>) <$> evalAndCache xs
where
notFound = fail ("cannot load module: " <> show name)
evalAndCache :: (MonadAnalysis term value m, Ord (LocationFor value)) => [term] -> m (EnvironmentFor value)
evalAndCache [] = pure mempty
evalAndCache (x:xs) = do
void $ evaluateModule x
env <- filterEnv <$> getExports <*> getGlobalEnv
modifyModuleTable (moduleTableInsert name env)
(env <>) <$> evalAndCache xs
-- TODO: If the set of exports is empty because no exports have been
-- defined, do we export all terms, or no terms? This behavior varies across
-- languages. We need better semantics rather than doing it ad-hoc.
filterEnv :: (Ord l) => Exports l a -> Environment l a -> Environment l a
filterEnv Exports{..} env
| Map.null unExports = env
| otherwise = Environment $ Map.foldrWithKey maybeInsert mempty unExports
where maybeInsert name (alias, address) accum =
maybe accum (\v -> Map.insert alias v accum) (address <|> envLookup name env)
-- | Lift a 'SubtermAlgebra' for an underlying analysis into a containing analysis. Use this when defining an analysis which can be composed onto other analyses to ensure that a call to 'analyzeTerm' occurs in the inner analysis and not the outer one.
liftAnalyze :: ( Coercible ( m term value (effects :: [* -> *]) value) (t m term value effects value)

View File

@ -3,6 +3,8 @@ module Control.Abstract.Evaluator
( MonadEvaluator(..)
, MonadEnvironment(..)
, modifyGlobalEnv
, modifyExports
, addExport
, MonadHeap(..)
, modifyHeap
, lookupHeap
@ -20,7 +22,7 @@ import Data.Abstract.Heap
import Data.Abstract.ModuleTable
import Data.Abstract.Value
import Data.Semigroup.Reducer
import Prelude hiding (fail)
import Prelude
import Prologue
-- | A 'Monad' providing the basic essentials for evaluation.
@ -45,14 +47,15 @@ class Monad m => MonadEnvironment value m | m -> value where
getGlobalEnv :: m (EnvironmentFor value)
-- | Set the global environment
putGlobalEnv :: EnvironmentFor value -> m ()
-- | Sets the global environment for the lifetime of the given action.
withGlobalEnv :: EnvironmentFor value -> m a -> m a
-- | Add an export to the global export state.
addExport :: Name -> (Name, Maybe (Address (LocationFor value) value)) -> m ()
-- | Get the global export state.
getExports :: m (Map Name (Name, Maybe (Address (LocationFor value) value)))
-- | Sets the exports state to the given map for the lifetime of the given action.
withExports :: Map Name (Name, Maybe (Address (LocationFor value) value)) -> m a -> m a
getExports :: m (ExportsFor value)
-- | Set the global export state.
putExports :: ExportsFor value -> m ()
-- | Sets the global export state for the lifetime of the given action.
withExports :: ExportsFor value -> m a -> m a
-- | Retrieve the local environment.
askLocalEnv :: m (EnvironmentFor value)
@ -70,11 +73,20 @@ class Monad m => MonadEnvironment value m | m -> value where
maybe (pure Nothing) (fmap Just . with) addr
-- | Update the global environment.
modifyGlobalEnv :: MonadEnvironment value m => (EnvironmentFor value -> EnvironmentFor value) -> m ()
modifyGlobalEnv :: MonadEnvironment value m => (EnvironmentFor value -> EnvironmentFor value) -> m ()
modifyGlobalEnv f = do
env <- getGlobalEnv
putGlobalEnv $! f env
-- | Update the global export state.
modifyExports :: MonadEnvironment value m => (ExportsFor value -> ExportsFor value) -> m ()
modifyExports f = do
exports <- getExports
putExports $! f exports
-- | Add an export to the global export state.
addExport :: MonadEnvironment value m => Name -> Name -> Maybe (Address (LocationFor value) value) -> m ()
addExport name alias = modifyExports . exportInsert name alias
-- | A 'Monad' abstracting a heap of values.
class Monad m => MonadHeap value m | m -> value where

View File

@ -48,6 +48,16 @@ class (Monad m, Show value) => MonadValue value m where
-- | Lift a Comparator (usually wrapping a function like == or <=) to a function on values.
liftComparison :: Comparator -> (value -> value -> m value)
-- | Lift a unary bitwise operator to values. This is usually 'complement'.
liftBitwise :: (forall a . Bits a => a -> a)
-> (value -> m value)
-- | Lift a binary bitwise operator to values. The Integral constraint is
-- necessary to satisfy implementation details of Haskell left/right shift,
-- but it's fine, since these are only ever operating on integral values.
liftBitwise2 :: (forall a . (Integral a, Bits a) => a -> a -> a)
-> (value -> value -> m value)
-- | Construct an abstract boolean value.
boolean :: Bool -> m value
@ -70,6 +80,9 @@ class (Monad m, Show value) => MonadValue value m where
-- | Construct an array of zero or more values.
array :: [value] -> m value
-- | Extract a 'ByteString' from a given value.
asString :: value -> m ByteString
-- | Eliminate boolean values. TODO: s/boolean/truthy
ifthenelse :: value -> m a -> m a -> m a
@ -133,9 +146,12 @@ instance ( Monad m
rational = pure . injValue . Value.Rational . Ratio
multiple = pure . injValue . Value.Tuple
array = pure . injValue . Value.Array
asString v
| Just (Value.String n) <- prjValue v = pure n
| otherwise = fail ("expected " <> show v <> " to be a string")
ifthenelse cond if' else'
| Just (Boolean b) <- prjValue cond = if b then if' else else'
| otherwise = fail ("not defined for non-boolean conditions: " <> show cond)
@ -188,6 +204,15 @@ instance ( Monad m
pair = (left, right)
liftBitwise operator target
| Just (Value.Integer (Number.Integer i)) <- prjValue target = integer $ operator i
| otherwise = fail ("Type error: invalid unary bitwise operation on " <> show target)
liftBitwise2 operator left right
| Just (Value.Integer (Number.Integer i), Value.Integer (Number.Integer j)) <- prjPair pair = integer $ operator i j
| otherwise = fail ("Type error: invalid binary bitwise operation on " <> show pair)
where pair = (left, right)
abstract names (Subterm body _) = do
l <- label body
injValue . Closure names l . bindEnv (foldr Set.delete (freeVariables body) names) <$> askLocalEnv
@ -236,6 +261,12 @@ instance (Alternative m, MonadEnvironment Type m, MonadFail m, MonadFresh m, Mon
(Int, Type.Float) -> pure Type.Float
_ -> unify left right
liftBitwise _ Int = pure Int
liftBitwise _ t = fail ("Invalid type passed to unary bitwise operation: " <> show t)
liftBitwise2 _ Int Int = pure Int
liftBitwise2 _ t1 t2 = fail ("Invalid types passed to binary bitwise operation: " <> show (t1, t2))
liftComparison (Concrete _) left right = case (left, right) of
(Type.Float, Int) -> pure Bool
(Int, Type.Float) -> pure Bool

View File

@ -1,12 +1,12 @@
{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, StandaloneDeriving #-}
module Data.Abstract.Environment where
import Prologue
import Data.Abstract.Address
import Data.Abstract.FreeVariables
import Data.Abstract.Live
import qualified Data.Map as Map
import Data.Semigroup.Reducer
import Prologue
import qualified Data.Map as Map
import qualified Data.Set as Set
-- | A map of names to addresses that represents the evaluation environment.
@ -15,6 +15,10 @@ newtype Environment l a = Environment { unEnvironment :: Map.Map Name (Address l
deriving instance Reducer (Name, Address l a) (Environment l a)
-- | A map of export names to an alias & address tuple.
newtype Exports l a = Exports { unExports :: Map.Map Name (Name, Maybe (Address l a)) }
deriving (Eq, Foldable, Functor, Generic1, Monoid, Ord, Semigroup, Show, Traversable)
-- | Lookup a 'Name' in the environment.
envLookup :: Name -> Environment l a -> Maybe (Address l a)
envLookup k = Map.lookup k . unEnvironment
@ -30,11 +34,8 @@ bindEnv :: (Ord l, Foldable t) => t Name -> Environment l a -> Environment l a
bindEnv names env = foldMap envForName names
where envForName name = maybe mempty (curry unit name) (envLookup name env)
bindExports :: (Ord l) => Map Name (Name, Maybe (Address l a)) -> Environment l a -> Environment l a
bindExports aliases env = Environment pairs
where
pairs = Map.foldrWithKey (\name (alias, address) accum ->
maybe accum (\v -> Map.insert alias v accum) (address <|> envLookup name env)) mempty aliases
exportInsert :: Name -> Name -> Maybe (Address l a) -> Exports l a -> Exports l a
exportInsert name alias address = Exports . Map.insert name (alias, address) . unExports
-- | Retrieve the 'Live' set of addresses to which the given free variable names are bound.
--
@ -45,8 +46,13 @@ envRoots env = foldMap (maybe mempty liveSingleton . flip envLookup env)
envAll :: (Ord l) => Environment l a -> Live l a
envAll (Environment env) = Live $ Set.fromList (Map.elems env)
-- Instances
instance Eq l => Eq1 (Environment l) where liftEq = genericLiftEq
instance Ord l => Ord1 (Environment l) where liftCompare = genericLiftCompare
instance Show l => Show1 (Environment l) where liftShowsPrec = genericLiftShowsPrec
instance Eq l => Eq1 (Exports l) where liftEq = genericLiftEq
instance Ord l => Ord1 (Exports l) where liftCompare = genericLiftCompare
instance Show l => Show1 (Exports l) where liftShowsPrec = genericLiftShowsPrec

View File

@ -5,16 +5,24 @@ import Prologue
import Data.Term
import Data.ByteString (intercalate)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Abstract.Path
-- | The type of variable names.
type Name = NonEmpty ByteString
-- | Construct a qualified name from a 'ByteString'
name :: ByteString -> Name
name x = x :| []
-- | Construct a qualified name from a list of 'ByteString's
qualifiedName :: [ByteString] -> Name
qualifiedName = NonEmpty.fromList
-- | Construct a qualified 'Name' from a `/` delimited path.
pathToQualifiedName :: ByteString -> Name
pathToQualifiedName = qualifiedName . splitOnPathSeparator
-- | User friendly 'ByteString' of a qualified 'Name'.
friendlyName :: Name -> ByteString
friendlyName xs = intercalate "." (NonEmpty.toList xs)

24
src/Data/Abstract/Path.hs Normal file
View File

@ -0,0 +1,24 @@
module Data.Abstract.Path where
import Prologue
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString as B
import Data.Char (ord)
-- | Split a 'ByteString' path on `/`, stripping quotes and any `./` prefix.
splitOnPathSeparator :: ByteString -> [ByteString]
splitOnPathSeparator = splitOnPathSeparator' id
splitOnPathSeparator' :: (ByteString -> ByteString) -> ByteString -> [ByteString]
splitOnPathSeparator' f = BC.split '/' . f . dropRelativePrefix . stripQuotes
stripQuotes :: ByteString -> ByteString
stripQuotes = B.filter (/= fromIntegral (ord '\"'))
dropRelativePrefix :: ByteString -> ByteString
dropRelativePrefix = BC.dropWhile (== '/') . BC.dropWhile (== '.')
dropExtension :: ByteString -> ByteString
dropExtension path = case BC.split '.' path of
[] -> path
xs -> BC.intercalate "." (Prelude.init xs)

View File

@ -134,6 +134,9 @@ instance Show1 Array where liftShowsPrec = genericLiftShowsPrec
-- | The environment for an abstract value type.
type EnvironmentFor v = Environment (LocationFor v) v
-- | The exports for an abstract value type.
type ExportsFor v = Exports (LocationFor v) v
-- | The 'Heap' for an abstract value type.
type HeapFor value = Heap (LocationFor value) value

View File

@ -107,7 +107,7 @@ instance Ord1 Identifier where liftCompare = genericLiftCompare
instance Show1 Identifier where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Identifier where
eval (Identifier name) = lookupWith deref name >>= maybe (fail ("free variable: " <> show name)) pure
eval (Identifier name) = lookupWith deref name >>= maybe (fail ("free variable: " <> show (friendlyName name))) pure
instance FreeVariables1 Identifier where
liftFreeVariables _ (Identifier x) = Set.singleton x

View File

@ -5,6 +5,7 @@ import Data.Abstract.Environment
import Data.Abstract.Evaluatable
import Diffing.Algorithm
import qualified Data.Map as Map
import Prelude hiding (fail)
import Prologue
data Function a = Function { functionContext :: ![a], functionName :: !a, functionParameters :: ![a], functionBody :: !a }
@ -223,7 +224,7 @@ instance Evaluatable QualifiedExport where
eval (QualifiedExport exportSymbols) = do
-- Insert the aliases with no addresses.
for_ exportSymbols $ \(name, alias) ->
addExport name (alias, Nothing)
addExport name alias Nothing
unit
@ -238,12 +239,15 @@ instance Show1 QualifiedExportFrom where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable QualifiedExportFrom where
eval (QualifiedExportFrom from exportSymbols) = do
let moduleName = freeVariable (subterm from)
importedEnv <- withGlobalEnv mempty (require moduleName)
importedEnv <- isolate (require moduleName)
-- Look up addresses in importedEnv and insert the aliases with addresses into the exports.
for_ exportSymbols $ \(name, alias) -> do
let address = Map.lookup name (unEnvironment importedEnv)
addExport name (alias, address)
maybe (cannotExport moduleName name) (addExport name alias . Just) address
unit
where
cannotExport moduleName name = fail $
"module " <> show (friendlyName moduleName) <> " does not export " <> show (friendlyName name)
newtype DefaultExport a = DefaultExport { defaultExport :: a }
@ -257,6 +261,8 @@ instance Evaluatable DefaultExport where
-- | Qualified Import declarations (symbols are qualified in calling environment).
--
-- If the list of symbols is empty copy and qualify everything to the calling environment.
data QualifiedImport a = QualifiedImport { qualifiedImportFrom :: !a, qualifiedImportAlias :: !a, qualifiedImportSymbols :: ![(Name, Name)]}
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
@ -267,21 +273,21 @@ instance Show1 QualifiedImport where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable QualifiedImport where
eval (QualifiedImport from alias xs) = do
let moduleName = freeVariable (subterm from)
importedEnv <- withGlobalEnv mempty (require moduleName)
importedEnv <- isolate (require moduleName)
modifyGlobalEnv (flip (Map.foldrWithKey copy) (unEnvironment importedEnv))
unit
where
prefix = freeVariable (subterm alias)
symbols = Map.fromList xs
copy = if Map.null symbols then qualifyInsert else directInsert
qualifyInsert k v rest = envInsert (prefix <> k) v rest
directInsert k v rest = maybe rest (\symAlias -> envInsert symAlias v rest) (Map.lookup k symbols)
copy = if Map.null symbols then insert else maybeInsert
insert sym = envInsert (prefix <> sym)
maybeInsert sym v env = maybe env (\symAlias -> insert symAlias v env) (Map.lookup sym symbols)
-- | Import declarations (symbols are added directly to the calling env).
-- | Import declarations (symbols are added directly to the calling environment).
--
-- If symbols is empty, just import the module for its side effects.
data Import a = Import { importFrom :: !a, importSymbols :: ![(Name, Name)] }
-- If the list of symbols is empty copy everything to the calling environment.
data Import a = Import { importFrom :: !a, importSymbols :: ![(Name, Name)], importWildcardToken :: !a }
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
instance Eq1 Import where liftEq = genericLiftEq
@ -289,31 +295,28 @@ instance Ord1 Import where liftCompare = genericLiftCompare
instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Import where
eval (Import from xs) = do
eval (Import from xs _) = do
let moduleName = freeVariable (subterm from)
importedEnv <- withGlobalEnv mempty (require moduleName)
modifyGlobalEnv (flip (Map.foldrWithKey directInsert) (unEnvironment importedEnv))
importedEnv <- isolate (require moduleName)
modifyGlobalEnv (flip (Map.foldrWithKey copy) (unEnvironment importedEnv))
unit
where
symbols = Map.fromList xs
directInsert k v rest = maybe rest (\symAlias -> envInsert symAlias v rest) (Map.lookup k symbols)
copy = if Map.null symbols then envInsert else maybeInsert
maybeInsert k v env = maybe env (\symAlias -> envInsert symAlias v env) (Map.lookup k symbols)
-- | A wildcard import (all symbols are added directly to the calling env)
--
-- Import a module updating the importing environments.
data WildcardImport a = WildcardImport { wildcardImportFrom :: !a, wildcardImportToken :: !a }
-- | Side effect only imports (no symbols made available to the calling environment).
data SideEffectImport a = SideEffectImport { sideEffectImportFrom :: !a, sideEffectImportToken :: !a }
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
instance Eq1 WildcardImport where liftEq = genericLiftEq
instance Ord1 WildcardImport where liftCompare = genericLiftCompare
instance Show1 WildcardImport where liftShowsPrec = genericLiftShowsPrec
instance Eq1 SideEffectImport where liftEq = genericLiftEq
instance Ord1 SideEffectImport where liftCompare = genericLiftCompare
instance Show1 SideEffectImport where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable WildcardImport where
eval (WildcardImport from _) = do
instance Evaluatable SideEffectImport where
eval (SideEffectImport from _) = do
let moduleName = freeVariable (subterm from)
importedEnv <- withGlobalEnv mempty (require moduleName)
modifyGlobalEnv (flip (Map.foldrWithKey envInsert) (unEnvironment importedEnv))
void $ isolate (require moduleName)
unit

View File

@ -157,9 +157,18 @@ instance Eq1 Bitwise where liftEq = genericLiftEq
instance Ord1 Bitwise where liftCompare = genericLiftCompare
instance Show1 Bitwise where liftShowsPrec = genericLiftShowsPrec
-- TODO: Implement Eval instance for Bitwise
instance Evaluatable Bitwise
instance Evaluatable Bitwise where
eval = traverse subtermValue >=> go where
genLShift x y = shiftL x (fromIntegral y)
genRShift x y = shiftR x (fromIntegral y)
go x = case x of
(BOr a b) -> liftBitwise2 (.|.) a b
(BAnd a b) -> liftBitwise2 (.&.) a b
(BXOr a b) -> liftBitwise2 xor a b
(LShift a b) -> liftBitwise2 genLShift a b
(RShift a b) -> liftBitwise2 genRShift a b
(UnsignedRShift a b) -> liftBitwise2 genRShift a b
(Complement a) -> liftBitwise complement a
-- | Member Access (e.g. a.b)
data MemberAccess a

View File

@ -8,9 +8,7 @@ module Language.Go.Assignment
import Assigning.Assignment hiding (Assignment, Error)
import Data.Abstract.FreeVariables
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString as B
import Data.Char (ord)
import Data.Abstract.Path
import Data.Record
import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1)
import Language.Go.Grammar as Grammar
@ -33,7 +31,7 @@ type Syntax =
, Declaration.Function
, Declaration.Import
, Declaration.QualifiedImport
, Declaration.WildcardImport
, Declaration.SideEffectImport
, Declaration.Method
, Declaration.MethodSignature
, Declaration.Module
@ -386,27 +384,27 @@ functionDeclaration = makeTerm <$> (symbol FunctionDeclaration <|> symbol FuncL
importDeclaration :: Assignment
importDeclaration = makeTerm'' <$> symbol ImportDeclaration <*> children (manyTerm (importSpec <|> importSpecList))
where
importSpecList = makeTerm <$> symbol ImportSpecList <*> children (manyTerm (importSpec <|> comment))
importSpec = makeTerm <$> symbol ImportSpec <*> children sideEffectImport
<|> makeTerm <$> symbol ImportSpec <*> children dotImport
<|> makeTerm <$> symbol ImportSpec <*> children namedImport
<|> makeTerm <$> symbol ImportSpec <*> children plainImport
dotImport = flip Declaration.WildcardImport <$> (makeTerm <$> symbol Dot <*> (Syntax.Identifier <$> (name <$> source))) <*> importFromPath
sideEffectImport = symbol BlankIdentifier *> source *> (Declaration.Import <$> importFromPath <*> pure [])
namedImport = flip Declaration.QualifiedImport <$> packageIdentifier <*> importFromPath <*> pure []
plainImport = symbol InterpretedStringLiteral >>= \loc -> do
names <- pathToNames <$> source
-- `import . "lib/Math"`
dotImport = inj <$> (makeImport <$> dot <*> importFromPath)
-- dotImport = inj <$> (flip Declaration.Import <$> (symbol Dot *> source *> pure []) <*> importFromPath)
-- `import _ "lib/Math"`
sideEffectImport = inj <$> (flip Declaration.SideEffectImport <$> underscore <*> importFromPath)
-- `import m "lib/Math"`
namedImport = inj <$> (flip Declaration.QualifiedImport <$> packageIdentifier <*> importFromPath <*> pure [])
-- `import "lib/Math"`
plainImport = inj <$> (symbol InterpretedStringLiteral >>= \loc -> do
names <- splitOnPathSeparator <$> source
let from = makeTerm loc (Syntax.Identifier (qualifiedName names))
let alias = makeTerm loc (Syntax.Identifier (name (last names))) -- Go takes `import "lib/Math"` and uses `Math` as the qualified name (e.g. `Math.Sin()`)
Declaration.QualifiedImport <$> pure from <*> pure alias <*> pure []
Declaration.QualifiedImport <$> pure from <*> pure alias <*> pure [])
makeImport dot path = Declaration.Import path [] dot
dot = makeTerm <$> symbol Dot <*> (Literal.TextElement <$> source)
underscore = makeTerm <$> symbol BlankIdentifier <*> (Literal.TextElement <$> source)
importSpec = makeTerm' <$> symbol ImportSpec <*> children (sideEffectImport <|> dotImport <|> namedImport <|> plainImport)
importSpecList = makeTerm <$> symbol ImportSpecList <*> children (manyTerm (importSpec <|> comment))
importFromPath = makeTerm <$> symbol InterpretedStringLiteral <*> (Syntax.Identifier <$> (pathToQualifiedName <$> source))
pathToQualifiedName = qualifiedName . pathToNames
pathToNames = BC.split '/' . (BC.dropWhile (== '/')) . (BC.dropWhile (== '.')) . stripQuotes
stripQuotes = B.filter (/= (fromIntegral (ord '\"')))
indexExpression :: Assignment
indexExpression = makeTerm <$> symbol IndexExpression <*> children (Expression.Subscript <$> expression <*> manyTerm expression)

View File

@ -36,9 +36,9 @@ type Syntax =
, Declaration.Comprehension
, Declaration.Decorator
, Declaration.Function
, Declaration.Import
, Declaration.QualifiedImport
, Declaration.Variable
, Declaration.WildcardImport
, Expression.Arithmetic
, Expression.Boolean
, Expression.Bitwise
@ -385,22 +385,24 @@ comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source)
import' :: Assignment
import' = makeTerm'' <$> symbol ImportStatement <*> children (manyTerm (aliasedImport <|> plainImport))
<|> makeTerm <$> symbol ImportFromStatement <*> children (Declaration.QualifiedImport <$> (identifier <|> emptyTerm) <*> emptyTerm <*> some (aliasImportSymbol <|> importSymbol))
<|> makeTerm <$> symbol ImportFromStatement <*> children (Declaration.WildcardImport <$> identifier <*> wildcard)
<|> makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> (identifier <|> emptyTerm) <*> (wildcard <|> (some (aliasImportSymbol <|> importSymbol))) <*> emptyTerm)
where
-- `import a as b`
aliasedImport = makeImport <$> symbol AliasedImport <*> children ((,) <$> expression <*> (Just <$> expression))
-- `import a`
plainImport = makeImport <$> location <*> ((,) <$> identifier <*> pure Nothing)
-- `from a import foo `
importSymbol = makeNameAliasPair <$> rawIdentifier <*> pure Nothing
-- `from a import foo as bar`
aliasImportSymbol = symbol AliasedImport *> children (makeNameAliasPair <$> rawIdentifier <*> (Just <$> rawIdentifier))
-- `from a import *`
wildcard = symbol WildcardImport *> source *> pure []
rawIdentifier = (name <$> identifier') <|> (qualifiedName <$> dottedName')
dottedName' = symbol DottedName *> children (some identifier')
identifier' = (symbol Identifier <|> symbol Identifier') *> source
makeNameAliasPair from (Just alias) = (from, alias)
makeNameAliasPair from Nothing = (from, from)
importSymbol = makeNameAliasPair <$> rawIdentifier <*> pure Nothing
aliasImportSymbol = symbol AliasedImport *> children (makeNameAliasPair <$> rawIdentifier <*> (Just <$> rawIdentifier))
wildcard = makeTerm <$> symbol WildcardImport <*> (Syntax.Identifier <$> (name <$> source))
aliasedImport = makeImport <$> symbol AliasedImport <*> children ((,) <$> expression <*> (Just <$> expression))
plainImport = makeImport <$> location <*> ((,) <$> identifier <*> pure Nothing)
makeImport loc (from, Just alias) = makeTerm loc (Declaration.QualifiedImport from alias [])
makeImport loc (from, Nothing) = makeTerm loc (Declaration.QualifiedImport from from [])

View File

@ -21,13 +21,13 @@ import qualified Data.Syntax.Expression as Expression
import qualified Data.Syntax.Literal as Literal
import qualified Data.Syntax.Statement as Statement
import qualified Data.Term as Term
import qualified Language.Ruby.Syntax as Ruby.Syntax
-- | The type of Ruby syntax.
type Syntax = '[
Comment.Comment
, Declaration.Class
, Declaration.Function
, Declaration.Import
, Declaration.Method
, Declaration.Module
, Expression.Arithmetic
@ -74,6 +74,8 @@ type Syntax = '[
, Syntax.Error
, Syntax.Identifier
, Syntax.Program
, Ruby.Syntax.Require
, Ruby.Syntax.Load
, []
]
@ -295,15 +297,20 @@ pair :: Assignment
pair = makeTerm <$> symbol Pair <*> children (Literal.KeyValue <$> expression <*> (expression <|> emptyTerm))
methodCall :: Assignment
methodCall = makeTerm' <$> symbol MethodCall <*> children (require <|> regularCall)
methodCall = makeTerm' <$> symbol MethodCall <*> children (require <|> load <|> regularCall)
where
regularCall = inj <$> (Expression.Call <$> pure [] <*> expression <*> args <*> (block <|> emptyTerm))
require = inj <$> (symbol Identifier *> do
s <- source
guard (elem s ["autoload", "load", "require", "require_relative"])
Declaration.Import <$> args' <*> pure [])
guard (elem s ["require", "require_relative"])
Ruby.Syntax.Require (s == "require_relative") <$> nameExpression)
load = inj <$> (symbol Identifier *> do
s <- source
guard (elem s ["load"])
Ruby.Syntax.Load <$> loadArgs)
args = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (many expression) <|> pure []
args' = makeTerm'' <$> (symbol ArgumentList <|> symbol ArgumentListWithParens) <*> children (many expression) <|> emptyTerm
loadArgs = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (some expression)
nameExpression = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children expression
call :: Assignment
call = makeTerm <$> symbol Call <*> children (Expression.MemberAccess <$> expression <*> (expression <|> args))

View File

@ -0,0 +1,54 @@
{-# LANGUAGE DeriveAnyClass #-}
module Language.Ruby.Syntax where
import Control.Monad (unless)
import Control.Abstract.Value (MonadValue)
import Data.Abstract.Environment
import Data.Abstract.Evaluatable
import Data.Abstract.Path
import Data.Abstract.Value (LocationFor)
import Diffing.Algorithm
import Prelude hiding (fail)
import Prologue
import qualified Data.Map as Map
data Require a = Require { requireRelative :: Bool, requirePath :: !a }
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
instance Eq1 Require where liftEq = genericLiftEq
instance Ord1 Require where liftCompare = genericLiftCompare
instance Show1 Require where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Require where
eval (Require _ x) = do
name <- pathToQualifiedName <$> (subtermValue x >>= asString)
importedEnv <- isolate (require name)
modifyGlobalEnv (flip (Map.foldrWithKey envInsert) (unEnvironment importedEnv))
unit
newtype Load a = Load { loadArgs :: [a] }
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
instance Eq1 Load where liftEq = genericLiftEq
instance Ord1 Load where liftCompare = genericLiftCompare
instance Show1 Load where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Load where
eval (Load [x]) = do
path <- subtermValue x >>= asString
doLoad path False
eval (Load [x, wrap]) = do
path <- subtermValue x >>= asString
shouldWrap <- subtermValue wrap >>= toBool
doLoad path shouldWrap
eval (Load _) = fail "invalid argument supplied to load, path is required"
doLoad :: (MonadAnalysis term value m, MonadValue value m, Ord (LocationFor value)) => ByteString -> Bool -> m value
doLoad path shouldWrap = do
let name = pathToQualifiedName path
importedEnv <- isolate (load name)
unless shouldWrap $ modifyGlobalEnv (flip (Map.foldrWithKey envInsert) (unEnvironment importedEnv))
unit
where pathToQualifiedName = qualifiedName . splitOnPathSeparator' dropExtension
-- TODO: autoload

View File

@ -9,9 +9,6 @@ module Language.TypeScript.Assignment
import Assigning.Assignment hiding (Assignment, Error)
import qualified Assigning.Assignment as Assignment
import Data.Abstract.FreeVariables
import qualified Data.ByteString as B (filter)
import qualified Data.ByteString.Char8 as BC
import Data.Char (ord)
import Data.Record
import Data.Syntax (emptyTerm, handleError, parseError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1, contextualize, postContextualize)
import qualified Data.Syntax as Syntax
@ -39,6 +36,7 @@ type Syntax = '[
, Declaration.TypeAlias
, Declaration.Import
, Declaration.QualifiedImport
, Declaration.SideEffectImport
, Declaration.DefaultExport
, Declaration.QualifiedExport
, Declaration.QualifiedExportFrom
@ -642,47 +640,39 @@ statementIdentifier = makeTerm <$> symbol StatementIdentifier <*> (Syntax.Identi
importStatement :: Assignment
importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> children ((,) <$> importClause <*> term fromClause)
<|> makeImport <$> symbol Grammar.ImportStatement <*> children requireImport
<|> makeImport <$> symbol Grammar.ImportStatement <*> children bareRequireImport
<|> makeTerm' <$> symbol Grammar.ImportStatement <*> children (requireImport <|> sideEffectImport)
where
-- Straightforward imports
makeImport loc (Just alias, symbols, from) = makeTerm loc (Declaration.QualifiedImport from alias symbols)
makeImport loc (Nothing, symbols, from) = makeTerm loc (Declaration.Import from symbols)
-- Import a file giving it an alias (e.g. import foo = require "./foo")
requireImport = symbol Grammar.ImportRequireClause *> children ((,,) <$> (Just <$> (term identifier)) <*> pure [] <*> term fromClause)
-- Import a file just for it's side effects (e.g. import "./foo")
bareRequireImport = (,,) <$> (pure Nothing) <*> pure [] <*> term fromClause
-- `import foo = require "./foo"`
requireImport = inj <$> (symbol Grammar.ImportRequireClause *> children (flip Declaration.QualifiedImport <$> (term identifier) <*> term fromClause <*> pure []))
-- `import "./foo"`
sideEffectImport = inj <$> (Declaration.SideEffectImport <$> term fromClause <*> emptyTerm)
-- `import { bar } from "./foo"`
namedImport = (,,,) <$> pure Prelude.False <*> pure Nothing <*> (symbol Grammar.NamedImports *> children (many importSymbol)) <*> emptyTerm
-- `import defaultMember from "./foo"`
defaultImport = (,,,) <$> pure Prelude.False <*> pure Nothing <*> (pure <$> (makeNameAliasPair <$> rawIdentifier <*> pure Nothing)) <*> emptyTerm
-- `import * as name from "./foo"`
namespaceImport = symbol Grammar.NamespaceImport *> children ((,,,) <$> pure Prelude.True <*> (Just <$> (term identifier)) <*> pure [] <*> emptyTerm)
-- Combinations of the above.
importClause = symbol Grammar.ImportClause *>
children (
(pure <$> namedImport)
<|> (pure <$> namespaceImport)
<|> ((\a b -> [a, b]) <$> defaultImport <*> (namedImport <|> namespaceImport))
<|> (pure <$> defaultImport))
-- Imports with import clauses
makeImportTerm1 loc from (Prelude.True, Just alias, symbols) = makeTerm loc (Declaration.QualifiedImport from alias symbols)
makeImportTerm1 loc from (Prelude.True, Nothing, symbols) = makeTerm loc (Declaration.QualifiedImport from from symbols)
makeImportTerm1 loc from (_, _, symbols) = makeTerm loc (Declaration.Import from symbols)
makeImportTerm1 loc from (Prelude.True, Just alias, symbols, _) = makeTerm loc (Declaration.QualifiedImport from alias symbols)
makeImportTerm1 loc from (Prelude.True, Nothing, symbols, _) = makeTerm loc (Declaration.QualifiedImport from from symbols)
makeImportTerm1 loc from (_, _, symbols, extra) = makeTerm loc (Declaration.Import from symbols extra)
makeImportTerm loc ([x], from) = makeImportTerm1 loc from x
makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs
importClause = symbol Grammar.ImportClause *>
children ( (pure <$> namedImport)
<|> (pure <$> namespaceImport)
<|> ((\a b -> [a, b]) <$> defaultImport <*> (namedImport <|> namespaceImport))
<|> (pure <$> defaultImport)
)
namedImport = (,,) <$> pure Prelude.False <*> pure Nothing <*> (symbol Grammar.NamedImports *> children (many importSymbol)) -- import { bar } from "./foo"
defaultImport = (,,) <$> pure Prelude.False <*> pure Nothing <*> (pure <$> (makeNameAliasPair <$> rawIdentifier <*> pure Nothing)) -- import defaultMember from "./foo"
namespaceImport = symbol Grammar.NamespaceImport *> children ((,,) <$> pure Prelude.True <*> (Just <$> (term identifier)) <*> pure []) -- import * as name from "./foo"
importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> (Just <$> rawIdentifier))
<|> symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> (pure Nothing))
importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> (pure Nothing)))
rawIdentifier = (symbol Identifier <|> symbol Identifier') *> (name <$> source)
makeNameAliasPair from (Just alias) = (from, alias)
makeNameAliasPair from Nothing = (from, from)
fromClause :: Assignment
fromClause = makeTerm <$> symbol Grammar.String <*> (Syntax.Identifier <$> (pathToQualifiedName <$> source))
where
pathToQualifiedName :: ByteString -> Name
pathToQualifiedName = qualifiedName . BC.split '/' . (BC.dropWhile (== '/')) . (BC.dropWhile (== '.')) . stripQuotes
stripQuotes :: ByteString -> ByteString
stripQuotes = B.filter (/= (fromIntegral (ord '\"')))
debuggerStatement :: Assignment
debuggerStatement = makeTerm <$> symbol Grammar.DebuggerStatement <*> (TypeScript.Syntax.Debugger <$ source)

View File

@ -8,6 +8,7 @@ module Prologue
import Data.Bifunctor.Join as X
import Data.Bits as X
import Data.ByteString as X (ByteString)
import Data.Functor.Both as X (Both, runBothWith, both)
import Data.IntMap as X (IntMap)

View File

@ -1,4 +1,3 @@
{-# LANGUAGE TypeApplications #-}
module Analysis.Go.Spec (spec) where
import Data.Abstract.Value

View File

@ -1,4 +1,3 @@
{-# LANGUAGE TypeApplications #-}
module Analysis.Python.Spec (spec) where
import Data.Abstract.Value

View File

@ -0,0 +1,35 @@
module Analysis.Ruby.Spec (spec) where
import Data.Abstract.Value
import Data.Map
import SpecHelpers
spec :: Spec
spec = parallel $ do
describe "evalutes Ruby" $ do
it "require_relative" $ do
env <- evaluate "main.rb"
let expectedEnv = Environment $ fromList [ (qualifiedName ["foo"], addr 0) ]
env `shouldBe` expectedEnv
it "load" $ do
env <- evaluate "load.rb"
let expectedEnv = Environment $ fromList [ (qualifiedName ["foo"], addr 0) ]
env `shouldBe` expectedEnv
it "load wrap" $ do
res <- evaluate' "load-wrap.rb"
fst res `shouldBe` Left "free variable: \"foo\""
snd res `shouldBe` Environment (fromList [ ])
where
addr = Address . Precise
fixtures = "test/fixtures/ruby/analysis/"
evaluate entry = snd <$> evaluate' entry
evaluate' entry = fst . fst . fst . fst <$>
evaluateFiles rubyParser
[ fixtures <> entry
, fixtures <> "foo.rb"
]

View File

@ -1,4 +1,3 @@
{-# LANGUAGE TypeApplications #-}
module Analysis.TypeScript.Spec (spec) where
import Data.Abstract.Value
@ -31,12 +30,18 @@ spec = parallel $ do
env <- evaluate "main2.ts"
env `shouldBe` Environment (fromList [])
it "fails exporting symbols not defined in the module" $ do
env <- fst <$> evaluate' "bad-export.ts"
env `shouldBe` Left "module \"foo\" does not export \"pip\""
where
addr = Address . Precise
fixtures = "test/fixtures/typescript/analysis/"
evaluate entry = snd . fst . fst . fst . fst <$>
evaluate entry = snd <$> evaluate' entry
evaluate' entry = fst . fst . fst . fst <$>
evaluateFiles typescriptParser
[ fixtures <> entry
, fixtures <> "a.ts"
, fixtures <> "foo.ts"
, fixtures <> "pip.ts"
]

View File

@ -2,6 +2,7 @@ module Main where
import qualified Analysis.Go.Spec
import qualified Analysis.Python.Spec
import qualified Analysis.Ruby.Spec
import qualified Analysis.TypeScript.Spec
import qualified Assigning.Assignment.Spec
import qualified Data.Diff.Spec
@ -27,6 +28,7 @@ main = hspec $ do
parallel $ do
describe "Analysis.Go" Analysis.Go.Spec.spec
describe "Analysis.Python" Analysis.Python.Spec.spec
describe "Analysis.Ruby" Analysis.Ruby.Spec.spec
describe "Analysis.TypeScript" Analysis.TypeScript.Spec.spec
describe "Assigning.Assignment" Assigning.Assignment.Spec.spec
describe "Data.Diff" Data.Diff.Spec.spec

View File

@ -11,7 +11,7 @@ module SpecHelpers (
import Data.Abstract.Address as X
import Data.Abstract.Environment as X
import Data.Abstract.FreeVariables as X
import Data.Abstract.FreeVariables as X hiding (dropExtension)
import Data.Abstract.Heap as X
import Data.Abstract.ModuleTable as X
import Data.Blob as X

View File

@ -7,14 +7,18 @@
->(Identifier) }
{ (Identifier)
->(Identifier) })
(WildcardImport
{ (Identifier)
->(Identifier) }
(Identifier))
(QualifiedImport
{ (Identifier)
->(Identifier) }
(Identifier)))
{+(Import
{+(Identifier)+}
{+(TextElement)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{-(Import
{-(Identifier)-}
{-(TextElement)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})
(Function
(Empty)
(Identifier)

View File

@ -7,14 +7,18 @@
->(Identifier) }
{ (Identifier)
->(Identifier) })
(WildcardImport
{ (Identifier)
->(Identifier) }
(Identifier))
(QualifiedImport
{ (Identifier)
->(Identifier) }
(Identifier)))
{+(Import
{+(Identifier)+}
{+(TextElement)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{-(Import
{-(Identifier)-}
{-(TextElement)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})
(Function
(Empty)
(Identifier)

View File

@ -5,9 +5,9 @@
(QualifiedImport
(Identifier)
(Identifier))
(WildcardImport
(Import
(Identifier)
(Identifier))
(TextElement))
(QualifiedImport
(Identifier)
(Identifier)))

View File

@ -5,9 +5,9 @@
(QualifiedImport
(Identifier)
(Identifier))
(WildcardImport
(Import
(Identifier)
(Identifier))
(TextElement))
(QualifiedImport
(Identifier)
(Identifier)))

View File

@ -4,17 +4,17 @@
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{+(WildcardImport
{+(Import
{+(Identifier)+}
{+(Identifier)+})+}
{+(TextElement)+})+}
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{-(WildcardImport
{-(Import
{-(Identifier)-}
{-(Identifier)-})-}
{-(TextElement)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}

View File

@ -4,17 +4,17 @@
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{+(WildcardImport
{+(Import
{+(Identifier)+}
{+(Identifier)+})+}
{+(TextElement)+})+}
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{-(WildcardImport
{-(Import
{-(Identifier)-}
{-(Identifier)-})-}
{-(TextElement)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}

View File

@ -4,9 +4,9 @@
(QualifiedImport
(Identifier)
(Identifier))
(WildcardImport
(Import
(Identifier)
(Identifier))
(TextElement))
(QualifiedImport
(Identifier)
(Identifier))

View File

@ -4,9 +4,9 @@
(QualifiedImport
(Identifier)
(Identifier))
(WildcardImport
(Import
(Identifier)
(Identifier))
(TextElement))
(QualifiedImport
(Identifier)
(Identifier))

View File

@ -1,41 +1,65 @@
(Program
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
(
(Import
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) })
(
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) }))
(Import
{ (Identifier)
->(Identifier) }))
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+})+}
{+(SideEffectImport
{+(Identifier)+}
{+(Empty)+})+}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})-}
{-(SideEffectImport
{-(Identifier)-}
{-(Empty)-})-})

View File

@ -1,41 +1,65 @@
(Program
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{ (Import
{-(Identifier)-})
{-(Identifier)-}
{-(Empty)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
(
(Import
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) })
(
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) }))
(Import
{ (Identifier)
->(Identifier) }))
{+(Identifier)+}
{+(Empty)+}) }
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+})+}
{+(SideEffectImport
{+(Identifier)+}
{+(Empty)+})+}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})-}
{-(SideEffectImport
{-(Identifier)-}
{-(Empty)-})-})

View File

@ -1,25 +1,33 @@
(Program
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier)))
(Identifier)
(Empty)))
(
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier)))
(Import
(Identifier)))
(SideEffectImport
(Identifier)
(Empty)))

View File

@ -1,25 +1,33 @@
(Program
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier)))
(Identifier)
(Empty)))
(
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier)))
(Import
(Identifier)))
(SideEffectImport
(Identifier)
(Empty)))

View File

@ -1,34 +1,34 @@
(Program
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(WildcardImport
{ (Import
{-(Identifier)-}
{-(Empty)-})
->(Import
{+(Identifier)+}
{+(Identifier)+})+}
{+(QualifiedImport
{+(Empty)+}) }
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{ (Import
{-(Identifier)-}
{-(Empty)-})
->(Import
{+(Empty)+}
{+(Empty)+})+}
{-(QualifiedImport
{+(Empty)+}) }
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(WildcardImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Import
{-(Empty)-}
{-(Empty)-})-})

View File

@ -1,34 +1,34 @@
(Program
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(WildcardImport
{+(Identifier)+}
{+(Identifier)+})+}
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Empty)+}
{+(Empty)+})+}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(WildcardImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Empty)-}
{-(Empty)-})-})

View File

@ -1,16 +1,16 @@
(Program
(QualifiedImport
(Import
(Identifier)
(Empty))
(QualifiedImport
(Import
(Identifier)
(Empty))
(WildcardImport
(Identifier)
(Identifier))
(QualifiedImport
(Import
(Identifier)
(Empty))
(QualifiedImport
(Import
(Identifier)
(Empty))
(Import
(Empty)
(Empty)))

View File

@ -1,19 +1,19 @@
(Program
(QualifiedImport
(Import
(Identifier)
(Empty))
(QualifiedImport
(Import
(Identifier)
(Empty))
(WildcardImport
(Identifier)
(Identifier))
(QualifiedImport
(Import
(Identifier)
(Empty))
(QualifiedImport
(Import
(Identifier)
(Empty))
(QualifiedImport
(Import
(Identifier)
(Empty))
(Import
(Empty)
(Empty)))

3
test/fixtures/ruby/analysis/foo.rb vendored Normal file
View File

@ -0,0 +1,3 @@
def foo(x)
return x
end

View File

@ -0,0 +1,3 @@
load "./foo.rb", true
foo(1)

3
test/fixtures/ruby/analysis/load.rb vendored Normal file
View File

@ -0,0 +1,3 @@
load "./foo.rb"
foo(1)

3
test/fixtures/ruby/analysis/main.rb vendored Normal file
View File

@ -0,0 +1,3 @@
require_relative "foo"
foo(1)

View File

@ -1,12 +1,11 @@
(Program
(Import
(Require
{ (TextElement)
->(TextElement) })
{+(Import
{+(
{+(Symbol)+}
{+(TextElement)+})+})+}
{-(Call
(Call
{ (Identifier)
->(Identifier) }
{+(Symbol)+}
{+(TextElement)+}
{-(Identifier)-}
{-(Identifier)-}
{-(Empty)-})-})
(Empty)))

View File

@ -1,12 +1,11 @@
(Program
(Import
(Require
{ (TextElement)
->(TextElement) })
{+(Call
(Call
{ (Identifier)
->(Identifier) }
{+(Identifier)+}
{+(Identifier)+}
{+(Empty)+})+}
{-(Import
{-(
{-(Symbol)-}
{-(TextElement)-})-})-})
{-(Symbol)-}
{-(TextElement)-}
(Empty)))

View File

@ -1,5 +1,5 @@
(Program
(Import
(Require
(TextElement))
(Call
(Identifier)

View File

@ -1,7 +1,8 @@
(Program
(Import
(Require
(TextElement))
(Import
(
(Symbol)
(TextElement))))
(Call
(Identifier)
(Symbol)
(TextElement)
(Empty)))

View File

@ -1,24 +1,30 @@
(Program
(DefaultExport
{(Class
{-(Identifier)-}
{-([])-})
->
(Function
{ (Class
{-(Identifier)-}
{-([])-})
->(Function
{+(Empty)+}
{+(Empty)+}
{+(Identifier)+}
{+(RequiredParameter
{+(Empty)+}
{+(Empty)+}
{+(Identifier)+}
{+(RequiredParameter
{+(Empty)+}
{+(Empty)+}
{+(Annotation{+(PredefinedType)+})+}
{+(Assignment{+(Identifier)+}{+(Empty)+})+})+}
{+(RequiredParameter
{+(Empty)+}
{+(Empty)+}
{+(Annotation{+(PredefinedType)+})+}
{+(Assignment{+(Identifier)+}{+(Empty)+})+})+}
{+({+(Return
{+(Annotation
{+(PredefinedType)+})+}
{+(Assignment
{+(Identifier)+}
{+(Empty)+})+})+}
{+(RequiredParameter
{+(Empty)+}
{+(Empty)+}
{+(Annotation
{+(PredefinedType)+})+}
{+(Assignment
{+(Identifier)+}
{+(Empty)+})+})+}
{+(
{+(Return
{+(Hash
{+(ShorthandPropertyIdentifier)+}
{+(ShorthandPropertyIdentifier)+})+})+})+})}))
{+(ShorthandPropertyIdentifier)+})+})+})+}) }))

View File

@ -1,10 +1,30 @@
(Program
(DefaultExport
{(Function
{ (Function
{-(Empty)-}
{-(Empty)-}
{-(Identifier)-}
{-(RequiredParameter
{-(Empty)-}
{-(Empty)-}
{-(Identifier)-}
{-(RequiredParameter{-(Empty)-}{-(Empty)-}{-(Annotation{-(PredefinedType)-})-}{-(Assignment{-(Identifier)-}{-(Empty)-})-})-}
{-(RequiredParameter{-(Empty)-}{-(Empty)-}{-(Annotation{-(PredefinedType)-})-}{-(Assignment{-(Identifier)-}{-(Empty)-})-})-}
{-({-(Return{-(Hash{-(ShorthandPropertyIdentifier)-}{-(ShorthandPropertyIdentifier)-})-})-})-})
->(Class{+(Identifier)+}{+([])+})}))
{-(Annotation
{-(PredefinedType)-})-}
{-(Assignment
{-(Identifier)-}
{-(Empty)-})-})-}
{-(RequiredParameter
{-(Empty)-}
{-(Empty)-}
{-(Annotation
{-(PredefinedType)-})-}
{-(Assignment
{-(Identifier)-}
{-(Empty)-})-})-}
{-(
{-(Return
{-(Hash
{-(ShorthandPropertyIdentifier)-}
{-(ShorthandPropertyIdentifier)-})-})-})-})
->(Class
{+(Identifier)+}
{+([])+}) }))

View File

@ -0,0 +1,2 @@
export { pip } from "./pip"
export { pip } from "./foo"

View File

@ -0,0 +1,5 @@
export { pip }
function pip() {
return "this is the pip function"
}

View File

@ -1,37 +1,81 @@
(Program
{(QualifiedExport)->(QualifiedExport)}
{(QualifiedExport)->(QualifiedExport)}
{ (QualifiedExport)
->(QualifiedExport) }
{ (QualifiedExport)
->(QualifiedExport) }
(DefaultExport
(VariableDeclaration
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))))
(DefaultExport
(VariableDeclaration
{-(Assignment{-(Empty)-}{-(Identifier)-}{-(Identifier)-})-}
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier){(Empty)->(Identifier)})
{+(Assignment{+(Empty)+}{+(Identifier)+}{+(Empty)+})+}
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))))
{-(Assignment
{-(Empty)-}
{-(Identifier)-}
{-(Identifier)-})-}
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
{ (Empty)
->(Identifier) })
{+(Assignment
{+(Empty)+}
{+(Identifier)+}
{+(Empty)+})+}
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))))
(DefaultExport
{(Identifier)->(Identifier)})
{+(DefaultExport
{+(Function{+(Empty)+}{+(Empty)+}{+(Identifier)+}{+([])+})+})+}
{ (Identifier)
->(Identifier) })
{+(DefaultExport
{+(Function
{+(Empty)+}
{+(Empty)+}
{+(Identifier)+}
{+([])+})+})+}
(DefaultExport
(Function(Empty)(Empty)(Empty)([])))
{+(QualifiedExport)+}
{+(DefaultExport
{+(TextElement)+})+}
{+(QualifiedExportFrom
{+(Identifier)+})+}
{+(QualifiedExportFrom
{+(Identifier)+})+}
{-(DefaultExport
{-(Function{-(Empty)-}{-(Empty)-}{-(Identifier)-}{-([])-})-})-}
{-(QualifiedExport)-}
{-(DefaultExport
{-(TextElement)-})-}
{-(QualifiedExportFrom
{-(Identifier)-})-}
{-(QualifiedExportFrom
{-(Identifier)-})-})
(Function
(Empty)
(Empty)
(Empty)
([])))
{+(QualifiedExport)+}
{+(DefaultExport
{+(TextElement)+})+}
{+(QualifiedExportFrom
{+(Identifier)+})+}
{+(QualifiedExportFrom
{+(Identifier)+})+}
{-(DefaultExport
{-(Function
{-(Empty)-}
{-(Empty)-}
{-(Identifier)-}
{-([])-})-})-}
{-(QualifiedExport)-}
{-(DefaultExport
{-(TextElement)-})-}
{-(QualifiedExportFrom
{-(Identifier)-})-}
{-(QualifiedExportFrom
{-(Identifier)-})-})

View File

@ -1,29 +1,83 @@
(Program
{(QualifiedExport)->(QualifiedExport)}
{(QualifiedExport)->(QualifiedExport)}
{ (QualifiedExport)
->(QualifiedExport) }
{ (QualifiedExport)
->(QualifiedExport) }
(DefaultExport
(VariableDeclaration
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))
(Assignment(Empty){(Identifier)->(Identifier)}(Empty))))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))
(Assignment
(Empty)
{ (Identifier)
->(Identifier) }
(Empty))))
(DefaultExport
(VariableDeclaration
{+(Assignment{+(Empty)+}{+(Identifier)+}{+(Identifier)+})+}
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier){(Identifier)->(Empty)})
{+(Assignment{+(Empty)+}{+(Identifier)+}{+(Empty)+})+}
{-(Assignment{-(Empty)-}{-(Identifier)-}{-(Empty)-})-}
{-(Assignment{-(Empty)-}{-(Identifier)-}{-(Empty)-})-}))
{+(Assignment
{+(Empty)+}
{+(Identifier)+}
{+(Identifier)+})+}
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
{ (Identifier)
->(Empty) })
{+(Assignment
{+(Empty)+}
{+(Identifier)+}
{+(Empty)+})+}
{-(Assignment
{-(Empty)-}
{-(Identifier)-}
{-(Empty)-})-}
{-(Assignment
{-(Empty)-}
{-(Identifier)-}
{-(Empty)-})-}))
(DefaultExport
{(Identifier)->(Identifier)})
{-(DefaultExport
{-(Function{-(Empty)-}{-(Empty)-}{-(Identifier)-}{-([])-})-})-}
{ (Identifier)
->(Identifier) })
{-(DefaultExport
{-(Function
{-(Empty)-}
{-(Empty)-}
{-(Identifier)-}
{-([])-})-})-}
(DefaultExport
(Function(Empty)(Empty)(Empty)([])))
{+(DefaultExport
{+(Function{+(Empty)+}{+(Empty)+}{+(Identifier)+}{+([])+})+})+}
{(QualifiedExport)->(QualifiedExport)}
(Function
(Empty)
(Empty)
(Empty)
([])))
{+(DefaultExport
{+(Function
{+(Empty)+}
{+(Empty)+}
{+(Identifier)+}
{+([])+})+})+}
{ (QualifiedExport)
->(QualifiedExport) }
(DefaultExport
{(TextElement)->(TextElement)})
{(QualifiedExportFrom {-(Identifier)-})->(QualifiedExportFrom {+(Identifier)+})}
{(QualifiedExportFrom {-(Identifier)-})->(QualifiedExportFrom {+(Identifier)+})})
{ (TextElement)
->(TextElement) })
{ (QualifiedExportFrom
{-(Identifier)-})
->(QualifiedExportFrom
{+(Identifier)+}) }
{ (QualifiedExportFrom
{-(Identifier)-})
->(QualifiedExportFrom
{+(Identifier)+}) })

View File

@ -3,19 +3,54 @@
(QualifiedExport)
(DefaultExport
(VariableDeclaration
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))))
(DefaultExport
(VariableDeclaration
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))))
(DefaultExport (Identifier))
(DefaultExport (Function(Empty)(Empty)(Empty)([])))
(DefaultExport (Function(Empty)(Empty)(Identifier)([])))
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))))
(DefaultExport
(Identifier))
(DefaultExport
(Function
(Empty)
(Empty)
(Empty)
([])))
(DefaultExport
(Function
(Empty)
(Empty)
(Identifier)
([])))
(QualifiedExport)
(DefaultExport (TextElement))
(QualifiedExportFrom (Identifier))
(QualifiedExportFrom (Identifier)))
(DefaultExport
(TextElement))
(QualifiedExportFrom
(Identifier))
(QualifiedExportFrom
(Identifier)))

View File

@ -3,19 +3,54 @@
(QualifiedExport)
(DefaultExport
(VariableDeclaration
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))))
(DefaultExport
(VariableDeclaration
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier)(Identifier))
(Assignment(Empty)(Identifier)(Empty))
(Assignment(Empty)(Identifier)(Empty))))
(DefaultExport(Identifier))
(DefaultExport(Function(Empty)(Empty)(Identifier)([])))
(DefaultExport(Function(Empty)(Empty)(Empty)([])))
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
(Identifier))
(Assignment
(Empty)
(Identifier)
(Empty))
(Assignment
(Empty)
(Identifier)
(Empty))))
(DefaultExport
(Identifier))
(DefaultExport
(Function
(Empty)
(Empty)
(Identifier)
([])))
(DefaultExport
(Function
(Empty)
(Empty)
(Empty)
([])))
(QualifiedExport)
(DefaultExport (TextElement))
(QualifiedExportFrom (Identifier))
(QualifiedExportFrom (Identifier)))
(DefaultExport
(TextElement))
(QualifiedExportFrom
(Identifier))
(QualifiedExportFrom
(Identifier)))

View File

@ -1,45 +1,68 @@
(Program
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
(
(Import
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) })
(
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) }))
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+})+}
{+(SideEffectImport
{+(Identifier)+}
{+(Empty)+})+}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})-}
{-(SideEffectImport
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})

View File

@ -1,45 +1,68 @@
(Program
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) }
(
(Import
{ (Identifier)
->(Identifier) })
{ (Import
{-(Identifier)-})
->(Import
{+(Identifier)+}) })
(
(Import
{ (Identifier)
->(Identifier) })
(QualifiedImport
{ (Identifier)
->(Identifier) }
{ (Identifier)
->(Identifier) }))
{+(Import
{+(Identifier)+})+}
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{ (Import
{-(Identifier)-}
{-(Empty)-})
->(Import
{+(Identifier)+}
{+(Empty)+}) }
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(Import
{+(Identifier)+}
{+(Empty)+})+})+}
{+(
{+(Import
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+})+}
{+(SideEffectImport
{+(Identifier)+}
{+(Empty)+})+}
{+(QualifiedImport
{+(Identifier)+}
{+(Identifier)+})+}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-}
{-(Import
{-(Identifier)-})-})
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(Import
{-(Identifier)-}
{-(Empty)-})-})-}
{-(
{-(Import
{-(Identifier)-}
{-(Empty)-})-}
{-(QualifiedImport
{-(Identifier)-}
{-(Identifier)-})-})-}
{-(SideEffectImport
{-(Identifier)-}
{-(Empty)-})-})

View File

@ -1,28 +1,36 @@
(Program
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier)))
(Identifier)
(Empty)))
(
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier)))
(Import
(Identifier))
(SideEffectImport
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier)))

View File

@ -1,25 +1,33 @@
(Program
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier))
(Identifier)
(Empty))
(
(Import
(Identifier))
(Identifier)
(Empty))
(Import
(Identifier)))
(Identifier)
(Empty)))
(
(Import
(Identifier))
(Identifier)
(Empty))
(QualifiedImport
(Identifier)
(Identifier)))
(Import
(Identifier)))
(SideEffectImport
(Identifier)
(Empty)))