The Haskell Refactorer, HaRe, and its API - PowerPoint PPT Presentation

About This Presentation
Title:

The Haskell Refactorer, HaRe, and its API

Description:

Rename an identifier. Promote/demote a definition to widen/narrow its scope ... mkLeaf = Leaf. mkNode :: a - (Tree a) - (Tree a) - Tree a. mkNode = Node ... – PowerPoint PPT presentation

Number of Views:50
Avg rating:3.0/5.0
Slides: 32
Provided by: hl1
Category:

less

Transcript and Presenter's Notes

Title: The Haskell Refactorer, HaRe, and its API


1
The Haskell Refactorer, HaRe, and its API
  • Huiqing Li
  • Claus Reinke
  • Simon Thompson
  • Computing Lab, University of Kent
  • www.cs.kent.ac.uk/projects/refactor-fp/

2
Outline
  • Refactoring
  • HaRe The Haskell Refactorer
  • HaRe Demo
  • The HaRe API
  • API Demo
  • Conclusion and Future Work

3
Refactoring
  • What? Changing the structure of existing code
    without changing its meaning.
  • Source-to-source
  • Functionality-preserving
  • Diffuse and bureaucratic
  • Bi-directional
  • Where and why? Development, maintenance,
  • To make the code easier to understand and modify
  • To improve code reuse, quality and productivity
  • Essential part of the programming process.

4
HaRe The Haskell Refactorer
  • A tool for refactoring Haskell 98 programs.
  • Full Haskell 98 coverage.
  • Driving concerns usability and extensibility.
  • Implemented in Haskell, using Programaticas
    frontends and Strafunskis generic traversals.
  • Integrated with the two program editors (X)Emacs
    and Vim.
  • Preserves both comments and layout style of the
    source.

5
Refactorings Implemented in HaRe
  • Structural Refactorings
  • Generalise a definition
  • e.g.

module Test1 where
module Test1 where g x x (g (x 1))
g m x x ((g m) (x
m)) module Test2 where ?
module Test2 where import Test1
import Test1 h y g y
h
y g 1 y
6
Refactorings Implemented in HaRe
  • Structural Refactorings (cont.)
  • Rename an identifier
  • Promote/demote a definition to widen/narrow its
    scope
  • Delete an unused function
  • Duplicate a definition
  • Unfold a definition
  • Introduce a definition to name an identified
    expression
  • Add an argument to a function
  • Remove an unused argument from a function

7
Refactorings Implemented in HaRe
  • Module Refactorings
  • Move a definition from one module to another
    module
  • e.g.

module Test1(g) where module
Test1 where g x x (g (x 1))

module Test2 where ?
module Test2 where import Test1
import Test1 h y g y
g x x ( g
( x 1))
h y g y
8
Refactorings Implemented in HaRe
  • Module Refactorings (cont.)
  • Clean the imports
  • Make the used entities explicitly imported
  • Add an item to the export list
  • Remove an item from the export list

9
Refactorings Implemented in HaRe
  • Data-oriented Refactorings
  • From concrete to abstract data-type (ADT), which
    is a composite refactoring built from a sequence
    of primitive refactorings.
  • Add field labels
  • Add discriminators
  • Add constructors
  • Remove (nested) pattern
  • Create ADT interface.

10
HaRe Demo
Demonstration of HaRe, hosted in Emacs
11
From concrete data type to ADT
module Tree where data Tree a Leaf a
Node a (Tree a) (Tree a) flatten Tree a -gt
a flatten (Leaf x ) x flatten (Node x l r
) x (flatten l flatten r)
12
From concrete data type to ADT
module Tree where data Tree a Leaf leaf1
a Node node1 a, node2 Tree a,
node3 Tree a flatten Tree a -gt
a flatten (Leaf x ) x flatten (Node x l r
) x (flatten l flatten r)
13
From concrete data type to ADT
module Tree where data Tree a Leaf leaf1
a Node node1 a, node2 Tree a,
node3 Tree a isLeaf (Tree a) -gt
Bool isLeaf (Leaf _) True isLeaf _ False
isNode (Tree a) -gt Bool isNode (Node _ _ _)
True isNode _ False flatten Tree a -gt
a flatten (Leaf x ) x flatten (Node x l r )
x (flatten l flatten r)
14
From concrete data type to ADT
module Tree where data Tree a Leaf leaf1
a Node node1 a, node2 Tree a,
node3 Tree a mkLeaf a -gt Tree a mkLeaf
Leaf mkNode a -gt (Tree a) -gt (Tree a) -gt Tree
a mkNode Node isLeaf (Tree a) -gt
Bool isLeaf (Leaf _) True isLeaf _ False
isNode (Tree a) -gt Bool isNode (Node _ _ _)
True isNode _ False flatten Tree a -gt
a flatten (Leaf x ) x flatten (Node x l r )
x (flatten l flatten r)
15
From concrete data type to ADT
module Tree where data Tree a Leaf leaf1
a Node node1 a, node2 Tree a,
node3 Tree a mkLeaf a -gt Tree a mkLeaf
Leaf mkNode a -gt (Tree a) -gt (Tree a) -gt
Tree a mkNode Node isLeaf (Tree a) -gt
Bool isLeaf (Leaf _) True isLeaf _ False
isNode (Tree a) -gt Bool isNode (Node _ _ _)
True isNode _ False flatten Tree a -gt
a flatten p isLeaf p (leaf1
p) flatten p isNode p (node1 p)
(flatten (node2 p) flatten (node3 p))
16
From concrete data type to ADT
module Tree (Tree,flatten,isLeaf,isNode,leaf1,mkLe
af,mkNode,node1,node2,node3) where data Tree
a Leaf leaf1 a Node node1 a,
node2 Tree a, node3 Tree a mkLeaf a -gt
Tree a mkLeaf Leaf mkNode a -gt (Tree a) -gt
(Tree a) -gt Tree a mkNode Node isLeaf
(Tree a) -gt Bool isLeaf (Leaf _) True isLeaf _
False isNode (Tree a) -gt Bool isNode (Node
_ _ _) True isNode _ False flatten Tree
a -gt a flatten p isLeaf p (leaf1
p) flatten p isNode p (node1 p)
(flatten (node2 p) flatten (node3 p))
17
Generalise a definition
--- Test1.hs module Test1(g) where -- a
generator g x x (g (x 1)) -- Test2.hs
module Test2 where import Test1 h y g y
18
Generalise a definition
--- Test1.hs module Test1(g) where -- a
generator g m x x ((g m) (x m)) -- Test2.hs
module Test2 where import Test1 h y g 1 y
19
Move a definition to another module
--- Test1.hs module Test1() where -- Test2.hs
module Test2 where import Test1 -- a
generator g m x x ((g m) (x m)) h y g 1 y
20
Clean imports
--- Test1.hs module Test1() where -- Test2.hs
module Test2 where -- a generator g m x x
((g m) (x m)) h y g 1 y
21
The HaRe API
  • A collection of functions for program analysis
    and transformation extracted from the HaRe.
  • Hidden layout and comment preservation in program
    transformation functions.
  • Programaticas abstract syntax for Haskell 98
  • Strafunskis library for AST traversals
  • HaRes API
  • make implementing primitive refactorings or
    general program transformations much easier.

22
The HaRe API
  • Program analysis API
  • Variable analysis
  • Property checking
  • Module interface (import and exports) analysis
  • Module and files
  • Program transformation API
  • Add/remove/update/swap program entities (e.g.
    declarations, expressions, parameters,
    identifiers, etc.)
  • Others
  • Parsing/writing
  • Name generators, from textual to AST syntax
    phrase,

23
API Demo
  • Example refactoring Swap the first two arguments
    of a function, say foo. This affects
  • The formal parameters of foo.
  • The arguments at the use-sites of foo throughout
    the program (could be a multi-module program).
  • The type signature.

24
API Demo
-- swap the first two arguments of a
function swapArgs fileName row col do (inscps,
exps, mod, ts)lt-parseSourceFile fileName
-- from text to program
let pnt locToPNT
fileName row col mod
if isFunPNT pnt mod
then -- deal with the current module
do rlt-applyRefac (doSwap pnt) (Just
(mod, ts)) fileName if
isExported pnt exps then
-- deal with the client modules.
do rs lt- applyRefacToClientMo
ds (doSwap pnt) fileName
writeRefactoredFiles False (rrs)
else
writeRefactoredFiles False r else
error "\nInvalid cursor position!"

-- more code to follow
25
API Demo
--- Inside a module doSwap pnt applyTP
(full_buTP (idTP adhocTP inMatch

adhocTP inExp
adhocTP
inDecl)) where inMatch ((HsMatch loc
fun pats rhs ds)HsMatchP) fun pnt
case pats of (p1p2ps) -gt
do pats'lt-swap p1 p2 pats
return (HsMatch loc fun pats' rhs
ds) _ -gt error
"Insufficient arguments to swap." inMatch m
return m inExp exp_at_((Exp (HsApp (Exp
(HsApp e e1)) e2))HsExpP) expToPNT e
pnt swap e1 e2 exp inExp e
return e


26
API Demo
inDecl (decl_at_(Dec (HsTypeSig loc is c
tp))HsDeclP) isTypeSigOf pnt decl
if length is 1 then do let ts
tyFunToList tp swap
(ts!!0) (ts!!1) ts -- assume no
type synonym is used. else error "This
type signature defines the type of more than one
identifiers." inDecl d return d tyFunToList
(Typ (HsTyFun t1 t2)) t1(tyFunToList t2)
tyFunToList t t
27
API Demo
Demonstration of the swap refactoring
28
Swap arguments
-- Test3.hs module Test3 where sumLength
String -gt Int-gt Int sumLength x y length x
length y -- Test4.hs module Test4 where
import Test3 test3 sumLength "abc" 1,2,3
29
Swap arguments
-- Test3.hs module Test3 where sumLength
Int -gt String-gt Int sumLength y x length x
length y -- Test4.hs module Test4 where
import Test3 test3 sumLength 1,2,3 "abc
30
Conclusion and Future Work
  • The API is relatively low-level, but essential
    for implementing program transformations.
  • Program appearance preservation hidden in the
    API.
  • Together with Strafunski, the API allows to write
    concise source-to-source program transformations
    and their side-conditions.
  • A framework for exploring your program
    transformation ideas.
  • In the future
  • Complete and improve the current API.
  • Look for some higher-level API.

31
www.cs.kent.ac.uk/projects/refactor-fp/
Write a Comment
User Comments (0)
About PowerShow.com