1
1
mirror of https://github.com/github/semantic.git synced 2024-12-01 09:15:01 +03:00

Merge branch 'master' into bracket-effect

This commit is contained in:
Patrick Thomson 2018-10-16 17:52:30 -04:00 committed by GitHub
commit ebda4bfaa1
4 changed files with 69 additions and 105 deletions

View File

@ -6,6 +6,7 @@ module Data.Term
, termOut
, injectTerm
, projectTerm
, guardTerm
, TermF(..)
, termSize
, hoistTerm
@ -35,6 +36,11 @@ termOut = termFOut . unTerm
projectTerm :: forall f syntax ann . (f :< syntax) => Term (Sum syntax) ann -> Maybe (f (Term (Sum syntax) ann))
projectTerm = Sum.project . termOut
guardTerm :: forall m f syntax ann . (f :< syntax, Alternative m)
=> Term (Sum syntax) ann
-> m (f (Term (Sum syntax) ann))
guardTerm = Sum.projectGuard . termOut
data TermF syntax ann recur = In { termFAnnotation :: ann, termFOut :: syntax recur }
deriving (Eq, Ord, Foldable, Functor, Show, Traversable)

View File

@ -34,7 +34,6 @@ import Semantic.Telemetry (LogQueue, StatQueue)
import System.Exit (die)
import System.FilePath.Posix (takeDirectory)
justEvaluating
= runM
. runPrintingTrace

View File

@ -1,29 +1,27 @@
{-# LANGUAGE ScopedTypeVariables, TypeFamilies, TypeOperators #-}
{-# OPTIONS_GHC -Wno-missing-signatures -Wno-missing-export-lists #-}
{-# OPTIONS_GHC -Wno-missing-signatures -Wno-missing-export-lists -Wno-incomplete-uni-patterns #-}
module Semantic.Util.Rewriting where
import Prelude hiding (id, (.), readFile)
import Prelude hiding (id, readFile, (.))
import Prologue
import Control.Abstract
import Control.Abstract.Matching
import Control.Category
import Data.Blob
import qualified Data.ByteString.Char8 as BC
import Text.Show.Pretty (pPrint)
import Control.Abstract.Matching
import Control.Rewriting hiding (fromMatcher, target)
import Data.Blob
import Data.History
import qualified Data.Language as Language
import Data.Machine
import Data.Machine.Runner
import Data.Project hiding (readFile)
import qualified Data.Source as Source
import qualified Data.Sum as Sum
import qualified Data.Syntax.Literal as Literal
import Data.Term
import Language.JSON.PrettyPrint
import Language.Ruby.PrettyPrint
import Language.Python.PrettyPrint
import Matching.Core
import Language.Ruby.PrettyPrint
import Parsing.Parser
import Prologue hiding (weaken)
import Reprinting.Pipeline
import Semantic.IO as IO
import Semantic.Task
@ -31,7 +29,7 @@ import Semantic.Task
testPythonFile = do
let path = "test/fixtures/python/reprinting/function.py"
src <- blobSource <$> readBlobFromPath (File path Language.Python)
tree <- parseFile miniPythonParser path
tree <- parseFile' miniPythonParser path
pure (src, tree)
testPythonPipeline = do
@ -53,7 +51,7 @@ testPythonPipeline''' = do
testRubyFile = do
let path = "test/fixtures/ruby/reprinting/infix.rb"
src <- blobSource <$> readBlobFromPath (File path Language.Ruby)
tree <- parseFile miniRubyParser path
tree <- parseFile' miniRubyParser path
pure (src, tree)
testRubyPipeline = do
@ -77,80 +75,58 @@ printToTerm = either (putStrLn . show) (BC.putStr . Source.sourceBytes)
testJSONFile = do
let path = "test/fixtures/javascript/reprinting/map.json"
src <- blobSource <$> readBlobFromPath (File path Language.JSON)
tree <- parseFile jsonParser path
tree <- parseFile' jsonParser path
pure (src, tree)
renameKey :: (Literal.TextElement :< fs, Literal.KeyValue :< fs, Apply Functor fs) => Term (Sum fs) History -> Term (Sum fs) History
renameKey p = case projectTerm p of
Just (Literal.KeyValue k v)
| Just (Literal.TextElement x) <- Sum.project (termOut k)
, x == "\"foo\""
-> let newKey = termIn (termAnnotation k) (inject (Literal.TextElement "\"fooA\""))
in remark Refactored (termIn (termAnnotation p) (inject (Literal.KeyValue newKey v)))
_ -> Term (fmap renameKey (unTerm p))
renameKey :: ( Literal.TextElement :< fs
, Apply Functor fs
, term ~ Term (Sum fs) History
)
=> Rewrite (env, term) (Literal.KeyValue term)
renameKey = do
Literal.KeyValue k v <- id
guard (projectTerm k == Just (Literal.TextElement "\"foo\""))
new <- modified (Literal.TextElement "\"fooA\"")
pure (Literal.KeyValue new v)
testRenameKey = do
(src, tree) <- testJSONFile
let tagged = renameKey (mark Unmodified tree)
let (Right tagged) = rewrite (somewhere' renameKey) () (mark Unmodified tree)
pPrint tagged
printToTerm $ runReprinter src defaultJSONPipeline tagged
increaseNumbers :: (Literal.Float :< fs, Apply Functor fs) => Term (Sum fs) History -> Term (Sum fs) History
increaseNumbers p = case Sum.project (termOut p) of
Just (Literal.Float t) -> remark Refactored (termIn (termAnnotation p) (inject (Literal.Float (t <> "0"))))
Nothing -> Term (fmap increaseNumbers (unTerm p))
increaseNumbers :: (term ~ Term (Sum fs) History) => Rewrite (env, term) (Literal.Float term)
increaseNumbers = do
(Literal.Float c) <- id
pure (Literal.Float (c <> "0"))
addKVPair :: forall effs syntax term .
( Apply Functor syntax
, Literal.Hash :< syntax
, Literal.Array :< syntax
, Literal.TextElement :< syntax
, Literal.KeyValue :< syntax
, term ~ Term (Sum syntax) History
) =>
ProcessT (Eff effs) (Either term (term, Literal.Hash term)) term
addKVPair = repeatedly $ do
t <- await
Data.Machine.yield (either id injKVPair t)
where
injKVPair :: (term, Literal.Hash term) -> term
injKVPair (origTerm, Literal.Hash xs) =
remark Refactored (injectTerm ann (Literal.Hash (xs <> [newItem])))
where
newItem = termIn ann (inject (Literal.KeyValue k v))
k = termIn ann (inject (Literal.TextElement "\"added\""))
v = termIn ann (inject (Literal.Array []))
ann = termAnnotation origTerm
addKVPair :: ( Literal.TextElement :< syn
, Literal.KeyValue :< syn
, Literal.Array :< syn
, Apply Functor syn
, term ~ Term (Sum syn) History
) => Rewrite (env, term) (Literal.Hash term)
addKVPair = do
Literal.Hash els <- id
k <- modified $ Literal.TextElement "\"added\""
v <- modified $ Literal.Array []
pair <- modified $ Literal.KeyValue k v
pure (Literal.Hash (pair : els))
testAddKVPair = do
(src, tree) <- testJSONFile
tagged <- runM $ cata (toAlgebra (fromMatcher matchHash ~> addKVPair)) (mark Unmodified tree)
let (Right tagged) = rewrite (somewhere addKVPair markRefactored) () (mark Unmodified tree)
printToTerm $ runReprinter src defaultJSONPipeline tagged
overwriteFloats :: forall effs syntax term .
( Apply Functor syntax
, Literal.Float :< syntax
, term ~ Term (Sum syntax) History
) =>
ProcessT (Eff effs) (Either term (term, Literal.Float term)) term
overwriteFloats = repeatedly $ do
t <- await
Data.Machine.yield (either id injFloat t)
where injFloat :: (term, Literal.Float term) -> term
injFloat (term, _) = remark Refactored (termIn (termAnnotation term) (inject (Literal.Float "0")))
overwriteFloats :: Rewrite (env, term) (Literal.Float term)
overwriteFloats = pure (Literal.Float "0")
testOverwriteFloats = do
(src, tree) <- testJSONFile
tagged <- runM $ cata (toAlgebra (fromMatcher matchFloat ~> overwriteFloats)) (mark Unmodified tree)
let (Right tagged) = rewrite (somewhere overwriteFloats markRefactored) () (mark Unmodified tree)
pPrint tagged
printToTerm $ runReprinter src defaultJSONPipeline tagged
findKV ::
( Literal.KeyValue :< syntax
, Literal.TextElement :< syntax
, term ~ Term (Sum syntax) History
) =>
Text -> ProcessT (Eff effs) term (Either term (term, Literal.KeyValue term))
findKV name = fromMatcher (kvMatcher name)
kvMatcher :: forall fs term .
( Literal.KeyValue :< fs
, Literal.TextElement :< fs
@ -163,41 +139,23 @@ kvMatcher name = matchM projectTerm target <* matchKey where
match Literal.textElementContent $
ensure (== name)
changeKV :: forall effs syntax term .
( Apply Functor syntax
, Literal.KeyValue :< syntax
, Literal.Array :< syntax
, Literal.Float :< syntax
, term ~ Term (Sum syntax) History
) =>
ProcessT (Eff effs) (Either term (term, Literal.KeyValue term)) term
changeKV = auto $ either id injKV
where
injKV :: (term, Literal.KeyValue term) -> term
injKV (term, Literal.KeyValue k v) = case projectTerm v of
Just (Literal.Array elems) -> remark Refactored (termIn ann (inject (Literal.KeyValue k (newArray elems))))
_ -> term
where newArray xs = termIn ann (inject (Literal.Array (xs <> [float])))
float = termIn ann (inject (Literal.Float "4"))
ann = termAnnotation term
changeKV :: ( Apply Functor syntax
, Literal.Array :< syntax
, Literal.Float :< syntax
, term ~ Term (Sum syntax) History
)
=> Rewrite (env, term) (Literal.KeyValue term)
changeKV = do
(Literal.KeyValue k v) <- id
(Literal.Array vals) <- guardTerm v
let float = remark Refactored (injectTerm (annotation v) (Literal.Float "4"))
let newArr = remark Refactored (injectTerm (annotation v) (Literal.Array (float:vals)))
pure (Literal.KeyValue k newArr)
testChangeKV = do
(src, tree) <- testJSONFile
tagged <- runM $ cata (toAlgebra (findKV "\"bar\"" ~> changeKV)) (mark Unmodified tree)
let (Right tagged) = rewrite (somewhere' changeKV) () (mark Unmodified tree)
printToTerm $ runReprinter src defaultJSONPipeline tagged
-- Temporary, until new KURE system lands.
fromMatcher :: Matcher from to -> ProcessT (Eff effs) from (Either from (from, to))
fromMatcher m = auto go where go x = maybe (Left x) (\y -> Right (x, y)) (stepMatcher x m)
-- Turn a 'ProccessT' into an FAlgebra.
toAlgebra :: (Traversable (Base t), Corecursive t)
=> ProcessT (Eff effs) t t
-> FAlgebra (Base t) (Eff effs t)
toAlgebra m t = do
inner <- sequenceA t
res <- runT1 (source (Just (embed inner)) ~> m)
pure (fromMaybe (embed inner) res)
parseFile :: Parser term -> FilePath -> IO term
parseFile parser = runTask . (parse parser <=< readBlob . file)
parseFile' :: Parser term -> FilePath -> IO term
parseFile' parser = runTask . (parse parser <=< readBlob . file)

View File

@ -8,11 +8,12 @@ import Data.Foldable
import Data.Functor.Foldable (cata, embed)
import qualified Data.Machine as Machine
import Control.Rewriting hiding (context)
import Data.Algebra
import Data.Blob
import qualified Data.Language as Language
import Data.Reprinting.Token
import Data.Reprinting.Scope
import Data.Reprinting.Token
import Data.Sum
import qualified Data.Syntax.Literal as Literal
import Language.JSON.PrettyPrint
@ -60,7 +61,7 @@ spec = describe "reprinting" $ do
printed `shouldBe` Right src
it "should be able to parse the output of a refactor" $ do
let tagged = increaseNumbers (mark Refactored tree)
let (Right tagged) = rewrite (somewhere increaseNumbers markRefactored) () (mark Unmodified tree)
let (Right printed) = runReprinter src defaultJSONPipeline tagged
tree' <- runTask (parse jsonParser (Blob printed path Language.JSON))
length tree' `shouldSatisfy` (/= 0)