Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions src/Text/Reprinter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ module Text.Reprinter
, RefactorType(..)
, Refactorable(..)
, Reprinting
, ZipperReprinting
, catchAll
, genReprinting
, reprint
, reprintSort
, wrapBasicReprinter
) where

-- Import solely for re-exporting for library clients
Expand Down Expand Up @@ -86,14 +88,20 @@ type Span = (Position, Position)
-- @i@ is the input type (something with a '[Char]'-like interface)
type Reprinting i m = forall node . (Typeable node) => node -> m (Maybe (RefactorType, i, Span))

-- | Zipper reprinting allows reprinting functions to take into account context
type ZipperReprinting i m = forall node . (Typeable node) => Zipper node -> m (Maybe (RefactorType, i, Span))

-- | Specify a refactoring type
data RefactorType = Before | After | Replace
deriving Show -- for debugging

-- | The reprint algorithm takes a refactoring (parameteric in
-- | some monad m) and turns an arbitrary pretty-printable type 'ast'
-- | into a monadic 'StringLike i' transformer.
reprint :: (Monad m, Data ast, StringLike i) => Reprinting i m -> ast -> i -> m i
reprint
:: (Monad m, Data ast, StringLike i)
=> ZipperReprinting i m -> ast -> i
-> m i
reprint reprinting ast input
-- If the input is empty return empty
| slNull input = return mempty
Expand All @@ -110,10 +118,13 @@ reprint reprinting ast input

-- | Take a refactoring and a zipper producing a stateful 'StringLike i'
-- | transformer with Position state.
enter :: (Monad m, StringLike i) => Reprinting i m -> Zipper ast -> StateT (Position, i) m i
enter
:: (Monad m, StringLike i, Typeable ast)
=> ZipperReprinting i m -> Zipper ast
-> StateT (Position, i) m i
enter reprinting zipper = do
-- Step 1: Apply a refactoring
refactoringInfo <- lift (query reprinting zipper)
refactoringInfo <- lift (reprinting zipper)

-- Step 2: Deal with refactored code or go to children
output <- case refactoringInfo of
Expand All @@ -138,9 +149,12 @@ enter reprinting zipper = do


-- | The reprint algorithm takes a refactoring (parameteric in
-- | some monad m) and turns an arbitrary pretty-printable type 'ast'
-- | into a monadic 'StringLike i' transformer.
reprintSort :: (Monad m, Data ast, StringLike i) => Reprinting i m -> ast -> i -> m i
-- some monad m) and turns an arbitrary pretty-printable type 'ast'
-- into a monadic 'StringLike i' transformer.
reprintSort
:: (Monad m, Data ast, StringLike i)
=> ZipperReprinting i m -> ast -> i
-> m i
reprintSort reprinting ast input
-- If the input is empty return empty
| slNull input = return mempty
Expand All @@ -157,8 +171,10 @@ reprintSort reprinting ast input


-- | Take a refactoring and a zipper to produce a list of refactorings
enter' :: (Monad m, StringLike i) => Reprinting i m -> Zipper ast
-> StateT (Position, i) m i
enter'
:: (Monad m, StringLike i, Typeable ast)
=> ZipperReprinting i m -> Zipper ast
-> StateT (Position, i) m i
enter' reprinting zipper = do
-- Step 1: Get refactorings via AST zipper traversal
rs <- lift $ getRefactorings reprinting zipper []
Expand All @@ -168,11 +184,13 @@ enter' reprinting zipper = do
where
sortBySpan = sortOn (\(_,_,sp) -> sp)

getRefactorings :: (Monad m, StringLike i) => Reprinting i m -> Zipper ast -> [(RefactorType, i, Span)]
-> m [(RefactorType, i, Span)]
getRefactorings
:: (Monad m, StringLike i, Typeable ast)
=> ZipperReprinting i m -> Zipper ast -> [(RefactorType, i, Span)]
-> m [(RefactorType, i, Span)]
getRefactorings reprinting zipper acc = do
-- Step 1: Apply a refactoring
refactoringInfo <- query reprinting zipper
refactoringInfo <- reprinting zipper
-- Step 2: Deal with refactored code or go to children
acc <- case refactoringInfo of
-- No refactoring; go to children
Expand All @@ -192,7 +210,10 @@ getRefactorings reprinting zipper acc = do
-- Otherwise return the empty string
Nothing -> return acc

splice :: (Monad m, StringLike i) => (RefactorType, i, Span) -> StateT (Position, i) m i
splice
:: (Monad m, StringLike i)
=> (RefactorType, i, Span)
-> StateT (Position, i) m i
splice (typ, output, (lb, ub)) = do
(cursor, inp) <- get
case typ of
Expand Down Expand Up @@ -255,3 +276,9 @@ genReprinting f z = case isRefactored z of
-- | Catch all generic query
catchAll :: Monad m => a -> m (Maybe b)
catchAll _ = return Nothing

wrapBasicReprinter
:: (Monad m, StringLike i)
=> Reprinting i m
-> ZipperReprinting i m
wrapBasicReprinter = query
4 changes: 2 additions & 2 deletions src/Text/Reprinter/Example.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ reprints.
refactor :: String -> String
refactor s =
runIdentity
. flip (reprint exprReprinter) s
. flip (reprint (wrapBasicReprinter exprReprinter)) s
. refactorZero
. parse $ s

Expand Down Expand Up @@ -291,7 +291,7 @@ eval (Var _ _ s) = get >>= return . lookup s
refactorComment :: String -> String
refactorComment input =
flip evalState []
. flip (reprint commentPrinter) input
. flip (reprint (wrapBasicReprinter commentPrinter)) input
. parse $ input
\end{code}

Expand Down
2 changes: 1 addition & 1 deletion tests/hspec/ReprinterSpec.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}

module ReprinterSpec where

Expand Down