mirror of
https://github.com/github/semantic.git
synced 2024-11-24 00:42:33 +03:00
Merge branch 'master' into semantic-tags
This commit is contained in:
commit
927d13b47c
@ -2,9 +2,6 @@ packages: . semantic-core semantic-python semantic-tags
|
|||||||
|
|
||||||
jobs: $ncpus
|
jobs: $ncpus
|
||||||
|
|
||||||
package semantic
|
|
||||||
ghc-options: +RTS -A128m -n2m -RTS
|
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/joshvera/proto3-suite.git
|
location: https://github.com/joshvera/proto3-suite.git
|
||||||
|
@ -4,6 +4,8 @@ module Data.Core.Parser
|
|||||||
, core
|
, core
|
||||||
, lit
|
, lit
|
||||||
, expr
|
, expr
|
||||||
|
, record
|
||||||
|
, comp
|
||||||
, lvalue
|
, lvalue
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ common haskell
|
|||||||
build-depends: base ^>=4.12
|
build-depends: base ^>=4.12
|
||||||
, fused-effects ^>= 0.5
|
, fused-effects ^>= 0.5
|
||||||
, semantic-core ^>= 0.0
|
, semantic-core ^>= 0.0
|
||||||
|
, text ^>= 1.2.3
|
||||||
, tree-sitter == 0.3.0.0
|
, tree-sitter == 0.3.0.0
|
||||||
, tree-sitter-python == 0.4.0.0
|
, tree-sitter-python == 0.4.0.0
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ test-suite test
|
|||||||
, containers ^>= 0.6
|
, containers ^>= 0.6
|
||||||
, directory ^>= 1.3.3
|
, directory ^>= 1.3.3
|
||||||
, exceptions ^>= 0.10.2
|
, exceptions ^>= 0.10.2
|
||||||
, filepath ^>= 1.4.2.1
|
, pathtype ^>= 0.8.1
|
||||||
, pretty-show ^>= 1.9.5
|
, pretty-show ^>= 1.9.5
|
||||||
, process ^>= 1.6.5
|
, process ^>= 1.6.5
|
||||||
, streaming ^>= 0.2.2
|
, streaming ^>= 0.2.2
|
||||||
@ -71,6 +72,5 @@ test-suite test
|
|||||||
, streaming-bytestring ^>= 0.1.6
|
, streaming-bytestring ^>= 0.1.6
|
||||||
, tasty ^>= 1.2.3
|
, tasty ^>= 1.2.3
|
||||||
, tasty-hunit ^>= 0.10.0.2
|
, tasty-hunit ^>= 0.10.0.2
|
||||||
, text ^>= 1.2.3
|
|
||||||
, trifecta >= 2 && <3
|
, trifecta >= 2 && <3
|
||||||
, unordered-containers ^>= 0.2.10
|
, unordered-containers ^>= 0.2.10
|
||||||
|
@ -1,26 +1,34 @@
|
|||||||
{-# LANGUAGE ConstraintKinds, DataKinds, DefaultSignatures, DeriveAnyClass, DeriveGeneric, DerivingStrategies,
|
{-# LANGUAGE ConstraintKinds, DataKinds, DefaultSignatures, DeriveAnyClass, DeriveGeneric, DerivingStrategies,
|
||||||
DerivingVia, DisambiguateRecordFields, FlexibleContexts, FlexibleInstances, NamedFieldPuns,
|
DerivingVia, DisambiguateRecordFields, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving,
|
||||||
OverloadedLists, OverloadedStrings, ScopedTypeVariables, StandaloneDeriving, TypeApplications,
|
NamedFieldPuns, OverloadedLists, OverloadedStrings, ScopedTypeVariables, StandaloneDeriving,
|
||||||
TypeOperators, UndecidableInstances #-}
|
TypeApplications, TypeOperators, UndecidableInstances #-}
|
||||||
|
|
||||||
module Language.Python.Core
|
module Language.Python.Core
|
||||||
( compile
|
( compile
|
||||||
|
, SourcePath
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
|
||||||
import Control.Effect hiding ((:+:))
|
import Control.Effect hiding ((:+:))
|
||||||
|
import Control.Effect.Reader
|
||||||
import Control.Monad.Fail
|
import Control.Monad.Fail
|
||||||
import Data.Core as Core
|
import Data.Core as Core
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
|
import qualified Data.Loc
|
||||||
import Data.Name as Name
|
import Data.Name as Name
|
||||||
|
import Data.String (IsString)
|
||||||
|
import Data.Text (Text)
|
||||||
import GHC.Generics
|
import GHC.Generics
|
||||||
import GHC.Records
|
import GHC.Records
|
||||||
import qualified Data.Loc
|
|
||||||
import qualified TreeSitter.Python.AST as Py
|
import qualified TreeSitter.Python.AST as Py
|
||||||
import TreeSitter.Span (Span)
|
import TreeSitter.Span (Span)
|
||||||
import qualified TreeSitter.Span as TreeSitter
|
import qualified TreeSitter.Span as TreeSitter
|
||||||
|
|
||||||
|
newtype SourcePath = SourcePath { rawPath :: Text }
|
||||||
|
deriving stock (Eq, Show)
|
||||||
|
deriving newtype IsString
|
||||||
|
|
||||||
-- We leave the representation of Core syntax abstract so that it's not
|
-- We leave the representation of Core syntax abstract so that it's not
|
||||||
-- possible for us to 'cheat' by pattern-matching on or eliminating a
|
-- possible for us to 'cheat' by pattern-matching on or eliminating a
|
||||||
-- compiled term.
|
-- compiled term.
|
||||||
@ -32,21 +40,38 @@ type CoreSyntax sig t = ( Member Core sig
|
|||||||
|
|
||||||
class Compile py where
|
class Compile py where
|
||||||
-- FIXME: we should really try not to fail
|
-- FIXME: we should really try not to fail
|
||||||
compile :: (CoreSyntax sig t, MonadFail m) => py -> m (t Name)
|
compile :: ( CoreSyntax syn t
|
||||||
|
, Member (Reader SourcePath) sig
|
||||||
|
, Carrier sig m
|
||||||
|
, MonadFail m
|
||||||
|
)
|
||||||
|
=> py
|
||||||
|
-> m (t Name)
|
||||||
|
|
||||||
default compile :: (MonadFail m, Show py) => py -> m (t Name)
|
default compile :: (MonadFail m, Show py) => py -> m (t Name)
|
||||||
compile = defaultCompile
|
compile = defaultCompile
|
||||||
|
|
||||||
compileCC :: (CoreSyntax sig t, MonadFail m) => py -> m (t Name) -> m (t Name)
|
compileCC :: ( CoreSyntax syn t
|
||||||
|
, Member (Reader SourcePath) sig
|
||||||
default compileCC :: (CoreSyntax sig t, MonadFail m) => py -> m (t Name) -> m (t Name)
|
, Carrier sig m
|
||||||
|
, MonadFail m
|
||||||
|
)
|
||||||
|
=> py
|
||||||
|
-> m (t Name)
|
||||||
|
-> m (t Name)
|
||||||
compileCC py cc = (>>>) <$> compile py <*> cc
|
compileCC py cc = (>>>) <$> compile py <*> cc
|
||||||
|
|
||||||
locate :: (HasField "ann" syntax Span, CoreSyntax sig t) => syntax -> t a -> t a
|
locate :: ( HasField "ann" syntax Span
|
||||||
locate syn = Core.annAt (locFromTSSpan (getField @"ann" syn))
|
, CoreSyntax syn t
|
||||||
where
|
, Member (Reader SourcePath) sig
|
||||||
locFromTSSpan (TreeSitter.Span (TreeSitter.Pos a b) (TreeSitter.Pos c d))
|
, Carrier sig m
|
||||||
= Data.Loc.Loc mempty (Data.Loc.Span (Data.Loc.Pos a b) (Data.Loc.Pos c d))
|
) => syntax -> t a -> m (t a)
|
||||||
|
locate syn item = do
|
||||||
|
fp <- asks @SourcePath rawPath
|
||||||
|
let locFromTSSpan (TreeSitter.Span (TreeSitter.Pos a b) (TreeSitter.Pos c d))
|
||||||
|
= Data.Loc.Loc fp (Data.Loc.Span (Data.Loc.Pos a b) (Data.Loc.Pos c d))
|
||||||
|
|
||||||
|
pure (Core.annAt (locFromTSSpan (getField @"ann" syn)) item)
|
||||||
|
|
||||||
-- | TODO: This is not right, it should be a reference to a Preluded
|
-- | TODO: This is not right, it should be a reference to a Preluded
|
||||||
-- NoneType instance, but it will do for now.
|
-- NoneType instance, but it will do for now.
|
||||||
@ -71,7 +96,7 @@ instance Compile (Py.Assignment Span) where
|
|||||||
compile it@Py.Assignment { Py.left = Py.ExpressionList { Py.extraChildren = [lhs] }, Py.right = Just rhs } = do
|
compile it@Py.Assignment { Py.left = Py.ExpressionList { Py.extraChildren = [lhs] }, Py.right = Just rhs } = do
|
||||||
target <- compile lhs
|
target <- compile lhs
|
||||||
value <- compile rhs
|
value <- compile rhs
|
||||||
pure . locate it $ target .= value
|
locate it $ target .= value
|
||||||
compile other = fail ("Unhandled assignment case: " <> show other)
|
compile other = fail ("Unhandled assignment case: " <> show other)
|
||||||
|
|
||||||
instance Compile (Py.AugmentedAssignment Span)
|
instance Compile (Py.AugmentedAssignment Span)
|
||||||
@ -81,7 +106,7 @@ instance Compile (Py.BinaryOperator Span)
|
|||||||
instance Compile (Py.Block Span) where
|
instance Compile (Py.Block Span) where
|
||||||
compile t = compileCC t (pure none)
|
compile t = compileCC t (pure none)
|
||||||
|
|
||||||
compileCC it@Py.Block{ Py.extraChildren = body} cc = locate it <$> foldr compileCC cc body
|
compileCC it@Py.Block{ Py.extraChildren = body} cc = locate it =<< foldr compileCC cc body
|
||||||
|
|
||||||
instance Compile (Py.BooleanOperator Span)
|
instance Compile (Py.BooleanOperator Span)
|
||||||
instance Compile (Py.BreakStatement Span)
|
instance Compile (Py.BreakStatement Span)
|
||||||
@ -106,15 +131,15 @@ deriving via CompileSum (Py.Expression Span) instance Compile (Py.Expression Spa
|
|||||||
instance Compile (Py.ExpressionStatement Span) where
|
instance Compile (Py.ExpressionStatement Span) where
|
||||||
compile it@Py.ExpressionStatement { Py.extraChildren = children } = do
|
compile it@Py.ExpressionStatement { Py.extraChildren = children } = do
|
||||||
actions <- traverse compile children
|
actions <- traverse compile children
|
||||||
pure . locate it $ do' (fmap (Nothing :<-) actions)
|
locate it $ do' (fmap (Nothing :<-) actions)
|
||||||
|
|
||||||
instance Compile (Py.ExpressionList Span) where
|
instance Compile (Py.ExpressionList Span) where
|
||||||
compile it@Py.ExpressionList { Py.extraChildren = exprs } = do
|
compile it@Py.ExpressionList { Py.extraChildren = exprs } = do
|
||||||
actions <- traverse compile exprs
|
actions <- traverse compile exprs
|
||||||
pure . locate it $ do' (fmap (Nothing :<-) actions)
|
locate it $ do' (fmap (Nothing :<-) actions)
|
||||||
|
|
||||||
|
|
||||||
instance Compile (Py.False Span) where compile it = pure . locate it $ bool False
|
instance Compile (Py.False Span) where compile it = locate it $ bool False
|
||||||
|
|
||||||
instance Compile (Py.Float Span)
|
instance Compile (Py.Float Span)
|
||||||
instance Compile (Py.ForStatement Span)
|
instance Compile (Py.ForStatement Span)
|
||||||
@ -127,7 +152,7 @@ instance Compile (Py.FunctionDefinition Span) where
|
|||||||
} = do
|
} = do
|
||||||
parameters' <- traverse param parameters
|
parameters' <- traverse param parameters
|
||||||
body' <- compile body
|
body' <- compile body
|
||||||
pure . locate it $ (pure name .= lams parameters' body')
|
locate it $ (pure name .= lams parameters' body')
|
||||||
where param (Py.IdentifierParameter (Py.Identifier _pann pname)) = pure (named' pname)
|
where param (Py.IdentifierParameter (Py.Identifier _pann pname)) = pure (named' pname)
|
||||||
param x = unimplemented x
|
param x = unimplemented x
|
||||||
unimplemented x = fail $ "unimplemented: " <> show x
|
unimplemented x = fail $ "unimplemented: " <> show x
|
||||||
@ -143,7 +168,7 @@ instance Compile (Py.IfStatement Span) where
|
|||||||
compile stmt = compileCC stmt (pure none)
|
compile stmt = compileCC stmt (pure none)
|
||||||
|
|
||||||
compileCC it@Py.IfStatement{ condition, consequence, alternative} cc =
|
compileCC it@Py.IfStatement{ condition, consequence, alternative} cc =
|
||||||
locate it <$> (if' <$> compile condition <*> compileCC consequence cc <*> foldr clause cc alternative)
|
locate it =<< (if' <$> compile condition <*> compileCC consequence cc <*> foldr clause cc alternative)
|
||||||
where clause (Right Py.ElseClause{ body }) _ = compileCC body cc
|
where clause (Right Py.ElseClause{ body }) _ = compileCC body cc
|
||||||
clause (Left Py.ElifClause{ condition, consequence }) rest =
|
clause (Left Py.ElifClause{ condition, consequence }) rest =
|
||||||
if' <$> compile condition <*> compileCC consequence cc <*> rest
|
if' <$> compile condition <*> compileCC consequence cc <*> rest
|
||||||
@ -162,7 +187,7 @@ instance Compile (Py.Module Span) where
|
|||||||
-- to top-level scope.
|
-- to top-level scope.
|
||||||
res <- traverse compile stmts
|
res <- traverse compile stmts
|
||||||
let names = concatMap toList res
|
let names = concatMap toList res
|
||||||
pure . locate it . record $ zip names res
|
locate it . record $ zip names res
|
||||||
|
|
||||||
instance Compile (Py.NamedExpression Span)
|
instance Compile (Py.NamedExpression Span)
|
||||||
instance Compile (Py.None Span)
|
instance Compile (Py.None Span)
|
||||||
@ -171,7 +196,7 @@ instance Compile (Py.NotOperator Span)
|
|||||||
instance Compile (Py.ParenthesizedExpression Span)
|
instance Compile (Py.ParenthesizedExpression Span)
|
||||||
|
|
||||||
instance Compile (Py.PassStatement Span) where
|
instance Compile (Py.PassStatement Span) where
|
||||||
compile it@Py.PassStatement {} = pure . locate it $ Core.unit
|
compile it@Py.PassStatement {} = locate it $ Core.unit
|
||||||
|
|
||||||
deriving via CompileSum (Py.PrimaryExpression Span) instance Compile (Py.PrimaryExpression Span)
|
deriving via CompileSum (Py.PrimaryExpression Span) instance Compile (Py.PrimaryExpression Span)
|
||||||
|
|
||||||
@ -179,8 +204,8 @@ instance Compile (Py.PrintStatement Span)
|
|||||||
|
|
||||||
instance Compile (Py.ReturnStatement Span) where
|
instance Compile (Py.ReturnStatement Span) where
|
||||||
compile it@Py.ReturnStatement { Py.extraChildren = vals } = case vals of
|
compile it@Py.ReturnStatement { Py.extraChildren = vals } = case vals of
|
||||||
Nothing -> pure . locate it $ none
|
Nothing -> locate it $ none
|
||||||
Just Py.ExpressionList { extraChildren = [val] } -> locate it <$> compile val
|
Just Py.ExpressionList { extraChildren = [val] } -> compile val >>= locate it
|
||||||
Just Py.ExpressionList { extraChildren = vals } -> fail ("unimplemented: return statement returning " <> show (length vals) <> " values")
|
Just Py.ExpressionList { extraChildren = vals } -> fail ("unimplemented: return statement returning " <> show (length vals) <> " values")
|
||||||
|
|
||||||
compileCC r _ = compile r
|
compileCC r _ = compile r
|
||||||
@ -195,12 +220,12 @@ deriving via CompileSum (Py.SimpleStatement Span) instance Compile (Py.SimpleSta
|
|||||||
instance Compile (Py.String Span)
|
instance Compile (Py.String Span)
|
||||||
instance Compile (Py.Subscript Span)
|
instance Compile (Py.Subscript Span)
|
||||||
|
|
||||||
instance Compile (Py.True Span) where compile it = pure . locate it $ bool True
|
instance Compile (Py.True Span) where compile it = locate it $ bool True
|
||||||
|
|
||||||
instance Compile (Py.TryStatement Span)
|
instance Compile (Py.TryStatement Span)
|
||||||
|
|
||||||
instance Compile (Py.Tuple Span) where
|
instance Compile (Py.Tuple Span) where
|
||||||
compile it@Py.Tuple { Py.extraChildren = [] } = pure . locate it $ Core.unit
|
compile it@Py.Tuple { Py.extraChildren = [] } = locate it $ Core.unit
|
||||||
compile it = fail ("Unimplemented: non-empty tuple " <> show it)
|
compile it = fail ("Unimplemented: non-empty tuple " <> show it)
|
||||||
|
|
||||||
instance Compile (Py.UnaryOperator Span)
|
instance Compile (Py.UnaryOperator Span)
|
||||||
@ -209,9 +234,17 @@ instance Compile (Py.WithStatement Span)
|
|||||||
instance Compile (Py.Yield Span)
|
instance Compile (Py.Yield Span)
|
||||||
|
|
||||||
class GCompileSum f where
|
class GCompileSum f where
|
||||||
gcompileSum :: (CoreSyntax sig t, MonadFail m) => f a -> m (t Name)
|
gcompileSum :: ( CoreSyntax syn t
|
||||||
|
, Member (Reader SourcePath) sig
|
||||||
|
, Carrier sig m
|
||||||
|
, MonadFail m
|
||||||
|
) => f a -> m (t Name)
|
||||||
|
|
||||||
gcompileCCSum :: (CoreSyntax sig t, MonadFail m) => f a -> m (t Name) -> m (t Name)
|
gcompileCCSum :: ( CoreSyntax syn t
|
||||||
|
, Member (Reader SourcePath) sig
|
||||||
|
, Carrier sig m
|
||||||
|
, MonadFail m
|
||||||
|
) => f a -> m (t Name) -> m (t Name)
|
||||||
|
|
||||||
instance GCompileSum f => GCompileSum (M1 D d f) where
|
instance GCompileSum f => GCompileSum (M1 D d f) where
|
||||||
gcompileSum (M1 f) = gcompileSum f
|
gcompileSum (M1 f) = gcompileSum f
|
||||||
|
@ -5,6 +5,12 @@ module Directive ( Directive (..)
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Name (Name)
|
||||||
|
import Data.Term (Term)
|
||||||
|
import Data.Core (Core)
|
||||||
|
import qualified Data.Core.Parser as Core.Parser
|
||||||
|
import qualified Data.Core.Pretty as Core.Pretty
|
||||||
import Data.ByteString.Char8 (ByteString)
|
import Data.ByteString.Char8 (ByteString)
|
||||||
import qualified Data.ByteString.Char8 as ByteString
|
import qualified Data.ByteString.Char8 as ByteString
|
||||||
import Data.List.NonEmpty (NonEmpty)
|
import Data.List.NonEmpty (NonEmpty)
|
||||||
@ -37,11 +43,13 @@ projects.
|
|||||||
|
|
||||||
-}
|
-}
|
||||||
data Directive = JQ ByteString -- | @# CHECK-JQ: expr@
|
data Directive = JQ ByteString -- | @# CHECK-JQ: expr@
|
||||||
|
| Tree (Term Core Name) -- | @# CHECK-TREE: core@
|
||||||
| Fails -- | @# CHECK-FAILS@ fails unless translation fails.
|
| Fails -- | @# CHECK-FAILS@ fails unless translation fails.
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
describe :: Directive -> String
|
describe :: Directive -> String
|
||||||
describe Fails = "<expect failure>"
|
describe Fails = "<expect failure>"
|
||||||
|
describe (Tree t) = Core.Pretty.showCore t
|
||||||
describe (JQ b) = ByteString.unpack b
|
describe (JQ b) = ByteString.unpack b
|
||||||
|
|
||||||
fails :: Trifecta.Parser Directive
|
fails :: Trifecta.Parser Directive
|
||||||
@ -52,8 +60,13 @@ jq = do
|
|||||||
Trifecta.string "# CHECK-JQ: "
|
Trifecta.string "# CHECK-JQ: "
|
||||||
JQ . ByteString.pack <$> many (Trifecta.noneOf "\n")
|
JQ . ByteString.pack <$> many (Trifecta.noneOf "\n")
|
||||||
|
|
||||||
|
tree :: Trifecta.Parser Directive
|
||||||
|
tree = do
|
||||||
|
void $ Trifecta.string "# CHECK-TREE: "
|
||||||
|
Tree <$> (Core.Parser.record <|> Core.Parser.comp)
|
||||||
|
|
||||||
directive :: Trifecta.Parser Directive
|
directive :: Trifecta.Parser Directive
|
||||||
directive = fails <|> jq
|
directive = Trifecta.choice [ fails, jq, tree ]
|
||||||
|
|
||||||
toplevel :: Trifecta.Parser (NonEmpty Directive)
|
toplevel :: Trifecta.Parser (NonEmpty Directive)
|
||||||
toplevel = directive `Trifecta.sepEndByNonEmpty` Trifecta.char '\n'
|
toplevel = directive `Trifecta.sepEndByNonEmpty` Trifecta.char '\n'
|
||||||
|
@ -5,6 +5,7 @@ module Main (main) where
|
|||||||
import qualified Analysis.Eval as Eval
|
import qualified Analysis.Eval as Eval
|
||||||
import Control.Effect
|
import Control.Effect
|
||||||
import Control.Effect.Fail
|
import Control.Effect.Fail
|
||||||
|
import Control.Effect.Reader
|
||||||
import Control.Monad hiding (fail)
|
import Control.Monad hiding (fail)
|
||||||
import Control.Monad.Catch
|
import Control.Monad.Catch
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
@ -23,6 +24,7 @@ import Data.Loc
|
|||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Name
|
import Data.Name
|
||||||
import Data.Term
|
import Data.Term
|
||||||
|
import Data.String (fromString)
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
import qualified Language.Python.Core as Py
|
import qualified Language.Python.Core as Py
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
@ -30,12 +32,14 @@ import Streaming
|
|||||||
import qualified Streaming.Process
|
import qualified Streaming.Process
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.FilePath
|
|
||||||
import qualified TreeSitter.Span as TS (Span)
|
import qualified TreeSitter.Span as TS (Span)
|
||||||
import qualified TreeSitter.Python as TSP
|
import qualified TreeSitter.Python as TSP
|
||||||
import qualified TreeSitter.Python.AST as TSP
|
import qualified TreeSitter.Python.AST as TSP
|
||||||
import qualified TreeSitter.Unmarshal as TS
|
import qualified TreeSitter.Unmarshal as TS
|
||||||
import Text.Show.Pretty (ppShow)
|
import Text.Show.Pretty (ppShow)
|
||||||
|
import qualified System.Path as Path
|
||||||
|
import qualified System.Path.Directory as Path
|
||||||
|
import System.Path ((</>))
|
||||||
|
|
||||||
import qualified Test.Tasty as Tasty
|
import qualified Test.Tasty as Tasty
|
||||||
import qualified Test.Tasty.HUnit as HUnit
|
import qualified Test.Tasty.HUnit as HUnit
|
||||||
@ -44,6 +48,7 @@ import Analysis.ScopeGraph
|
|||||||
import qualified Directive
|
import qualified Directive
|
||||||
import Instances ()
|
import Instances ()
|
||||||
|
|
||||||
|
|
||||||
assertJQExpressionSucceeds :: Show a => Directive.Directive -> a -> Term (Ann :+: Core) Name -> HUnit.Assertion
|
assertJQExpressionSucceeds :: Show a => Directive.Directive -> a -> Term (Ann :+: Core) Name -> HUnit.Assertion
|
||||||
assertJQExpressionSucceeds directive tree core = do
|
assertJQExpressionSucceeds directive tree core = do
|
||||||
bod <- case scopeGraph Eval.eval [File interactive core] of
|
bod <- case scopeGraph Eval.eval [File interactive core] of
|
||||||
@ -68,29 +73,38 @@ assertJQExpressionSucceeds directive tree core = do
|
|||||||
catch @_ @Streaming.Process.ProcessExitedUnsuccessfully jqPipeline $ \err -> do
|
catch @_ @Streaming.Process.ProcessExitedUnsuccessfully jqPipeline $ \err -> do
|
||||||
HUnit.assertFailure (unlines [errorMsg, dirMsg, jsonMsg, astMsg, treeMsg, treeMsg', show err])
|
HUnit.assertFailure (unlines [errorMsg, dirMsg, jsonMsg, astMsg, treeMsg, treeMsg', show err])
|
||||||
|
|
||||||
fixtureTestTreeForFile :: HasCallStack => FilePath -> Tasty.TestTree
|
fixtureTestTreeForFile :: HasCallStack => Path.RelFile -> Tasty.TestTree
|
||||||
fixtureTestTreeForFile fp = HUnit.testCaseSteps fp $ \step -> withFrozenCallStack $ do
|
fixtureTestTreeForFile fp = HUnit.testCaseSteps (Path.toString fp) $ \step -> withFrozenCallStack $ do
|
||||||
fileContents <- ByteString.readFile ("semantic-python/test/fixtures" </> fp)
|
let fullPath = Path.relDir "semantic-python/test/fixtures" </> fp
|
||||||
|
|
||||||
|
fileContents <- ByteString.readFile (Path.toString fullPath)
|
||||||
directives <- case Directive.parseDirectives fileContents of
|
directives <- case Directive.parseDirectives fileContents of
|
||||||
Right dir -> pure dir
|
Right dir -> pure dir
|
||||||
Left err -> HUnit.assertFailure ("Directive parsing error: " <> err)
|
Left err -> HUnit.assertFailure ("Directive parsing error: " <> err)
|
||||||
|
|
||||||
result <- TS.parseByteString TSP.tree_sitter_python fileContents
|
result <- TS.parseByteString TSP.tree_sitter_python fileContents
|
||||||
let coreResult = fmap (Control.Effect.run . runFail . Py.compile @(TSP.Module TS.Span) @_ @(Term (Ann :+: Core))) result
|
let coreResult = Control.Effect.run
|
||||||
|
. runFail
|
||||||
|
. runReader (fromString @Py.SourcePath . Path.toString $ fp)
|
||||||
|
. Py.compile @(TSP.Module TS.Span) @_ @(Term (Ann :+: Core))
|
||||||
|
<$> result
|
||||||
|
|
||||||
for_ directives $ \directive -> do
|
for_ directives $ \directive -> do
|
||||||
step (Directive.describe directive)
|
step (Directive.describe directive)
|
||||||
case coreResult of
|
case (coreResult, directive) of
|
||||||
Left err -> HUnit.assertFailure ("Parsing failed: " <> err)
|
(Right (Left _), Directive.Fails) -> pure ()
|
||||||
Right (Left _) | directive == Directive.Fails -> pure ()
|
(Left err, _) -> HUnit.assertFailure ("Parsing failed: " <> err)
|
||||||
Right (Right _) | directive == Directive.Fails -> HUnit.assertFailure ("Expected translation to fail")
|
(Right (Left err), _) -> HUnit.assertFailure ("Compilation failed: " <> err)
|
||||||
Right (Right item) -> assertJQExpressionSucceeds directive result item
|
(Right (Right _), Directive.Fails) -> HUnit.assertFailure ("Expected translation to fail")
|
||||||
Right (Left err) -> HUnit.assertFailure ("Compilation failed: " <> err)
|
(Right (Right item), Directive.JQ _) -> assertJQExpressionSucceeds directive result item
|
||||||
|
(Right (Right item), Directive.Tree t) -> let msg = "lhs = " <> showCore t <> "\n rhs " <> showCore item'
|
||||||
|
item' = stripAnnotations item
|
||||||
|
in HUnit.assertEqual msg t item' where
|
||||||
|
|
||||||
milestoneFixtures :: IO Tasty.TestTree
|
milestoneFixtures :: IO Tasty.TestTree
|
||||||
milestoneFixtures = do
|
milestoneFixtures = do
|
||||||
files <- liftIO (listDirectory "semantic-python/test/fixtures")
|
files <- liftIO (Path.filesInDir (Path.relDir "semantic-python/test/fixtures"))
|
||||||
let pythons = sort (filter ("py" `isExtensionOf`) files)
|
let pythons = sort (filter (Path.hasExtension ".py") files)
|
||||||
pure $ Tasty.testGroup "Translation" (fmap fixtureTestTreeForFile pythons)
|
pure $ Tasty.testGroup "Translation" (fmap fixtureTestTreeForFile pythons)
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
# CHECK-JQ: .scope == {} and .tree.contents == []
|
# CHECK-JQ: .scope == {}
|
||||||
|
# CHECK-TREE: #record {}
|
||||||
()
|
()
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# CHECK-JQ: .tree.contents[0][1].contents[1].contents.value.value == []
|
# CHECK-TREE: #record { foo : foo = (\a -> a) }
|
||||||
def foo(a):
|
def foo(a):
|
||||||
return a
|
return a
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# CHECK-JQ: .tree.contents[0][1].contents[1].contents.value.value == []
|
# CHECK-TREE: #record { foo : foo = (\a -> a) }
|
||||||
|
|
||||||
def foo(a):
|
def foo(a):
|
||||||
return a
|
return a
|
||||||
|
@ -329,8 +329,6 @@ library
|
|||||||
, tree-sitter-java == 0.2.0.0
|
, tree-sitter-java == 0.2.0.0
|
||||||
if flag(release)
|
if flag(release)
|
||||||
cpp-options: -DCOMPUTE_GIT_SHA
|
cpp-options: -DCOMPUTE_GIT_SHA
|
||||||
else
|
|
||||||
ghc-options: +RTS -A128m -n2m -RTS
|
|
||||||
|
|
||||||
executable semantic
|
executable semantic
|
||||||
import: haskell, dependencies, executable-flags
|
import: haskell, dependencies, executable-flags
|
||||||
|
Loading…
Reference in New Issue
Block a user