Presentation on theme: "Progress on ‘HaRe: The Haskell Refactorer’ Huiqing Li, Claus Reinke, Simon Thompson Computing Laboratory, University of Kent Refactoring is the process."— Presentation transcript:
Progress on ‘HaRe: The Haskell Refactorer’ Huiqing Li, Claus Reinke, Simon Thompson Computing Laboratory, University of Kent Refactoring is the process of improving the design of existing code without changing their functionality. Its key characteristic is the focus on the structural change, strictly separated from changes in functionality. If applied properly, refactoring can make a program easier to understand or modify. Refactorings are ‘diffuse’ and ‘bureaucratic’ in the sense that they have an effect not only at the point where they are initiated, but also at the places where the refactored component is used. An elementary refactoring is a refactoring that can not be decomposed into simpler refactorings, whereas a composite refactoring can be decomposed into a number of elementary refactorings. The Project: Refactoring Functional Programs Tool support is considered invaluable as it is more reliable and allows refactorings to be done (and undone) easily. sum  = 0 sum (h:t) = (+) h (sum t) main = print $ sum [1..4] sum n  = n sum n (h:t) = (+) h (sum n t) main = print $ sum 0 [1..4] sum c n  = n sum c n (h:t) = c h (sum c n t) main = print $ sum (+) 0 [1..4]. Explore the prospects of refactoring functional programs taking Haskell as a case-study. Build the HaRe tool to explore the practicalities of refactoring, and to support refactoring Haskell programs. What is Refactoring? A Simple Example fold c n  = n fold c n (h:t) = c h (fold c n t) main = print $ fold (+) 0 [1..4] generalisation renaming
Structural Refactorings Rename an identifier Delete an unused function Duplicate a definition. Promote a definition to a wider scope Demote a definition to narrow its scope Unfold a definition Introduce a definition to name an identified expression Generalise a definition Add an argument to a function Remove an unused argument from a function Module Refactorings Clean the import list Make the used entities explicitly imported Add an item to the export list Remove an item from the export list Move a definition from one module to another module Data-oriented Refactorings From concrete to abstract data-type (ADT), which is a composite refactoring built from a set of primitive refactorings: Add field labels Add discriminators Add constructors Remove nested patterns Remove patterns Create ADT interface A system designed to support refactoring Haskell programs. Full Haskell 98 coverage. Integrated into two program editors: (X)Emacs and Vim. Preserves both comments and layout of refactored program. Implemented in Haskell using Programatica’s frontends and Strafunski’s generic programming technique. Driving concerns: usability and solid basis for extensions. The first version of HaRe was released in October 2003. The current version is available online at: http://www.cs.kent.ac.uk/projects/refactor-fp All the implemented refactorings are now module-aware. Added new refactorings for the module system. Added data-oriented refactorings. Evolved architecture to allow the end users to define their own refactorings. HaRe: the Haskell Refactorer What’s New in HaRe? Refactorings Implemented in HaRe
Information gathering using the Programatica front-end for Haskell (lexer,parser, type checker and module analysis) Program analysis and transformation using Strafunski's generic traversal library Program rendering by extracting program source from token stream program source refactored program source HaRe preserves the comments and layout of refactored programs by making use of the white space and comment information in the token stream, as well as the location information in both the token stream and the abstract syntax tree(AST). Both the AST and the token stream are modified during the program transformation process. Snapshots of HaRe Embedded in Emacs Implementing a Refactoring After applying the ‘From concrete to abstract data type refactoring’ to the data type Tree:
Hidden token stream manipulation. RefacLocUtils is a library for token stream manipulation. Its core is a layout adjustment algorithm which keeps the program’s layout correct after a modification to the token stream. An API for program analysis and transformation. This API forms the basis for implementing primitive refactorings. Open architecture. Design your own refactorings. Composite Refactorings Elementary Refactorings RefacUtils ProgramaticaStrafunski RefacLocUtils The refactoring group at UKC: firstname.lastname@example.org@kent.ac.uk Huiqing Li email@example.com@kent.ac.uk Claus Reinke firstname.lastname@example.org@kent.ac.uk Simon Thompson email@example.com@kent.ac.uk Populate more refactorings into HaRe, such as removing duplicated code, monadification and further data-centred refactorings. Finalise the API for user-defined refactorings and further investigate the composition of refactorings. Extend HaRe to handle ‘no-source’ files. Develop proofs of correctness for a variety of the refactorings implemented in HaRe. Extend HaRe to support Haskell 98 extensions. Testing by applying HaRe to medium/large-size Haskell 98 programs. Clarify and prove concepts by formalization. The Architecture of HaRe Evaluation of HaRe Future Directions Contact Information The project is funded by EPSRC. We are grateful to Programatica (http://www.cse.ogi.edu/PacSoft/projects/programatica/) andhttp://www.cse.ogi.edu/PacSoft/projects/programatica/ Strafunski (http://www.cs.vu.nl/Strafunski/) development teams.http://www.cs.vu.nl/Strafunski/ -- Example: Swapping the first two arguments to the function pn in the AST mod doSwap pn mod = applyTP (full_buTP (idTP `adhocTP` swapInMatch `adhocTP` swapInExp)) mod where swapInMatch ((HsMatch loc fun pats rhs ds)::HsMatchP) | pNTtoPN fun == pn = case pats of (p1:p2:ps) -> do swapInToks p1 p2 return (HsMatch loc fun (p2:p1:ps) rhs ds) _ -> error "Insufficient arguments to swap." swapInExp ((Exp (HsApp (Exp (HsApp e e1)) e2))::HsExpP) | expToPN e ==pn = do swapInToks e1 e2 return (Exp (HsApp (Exp (HsApp e e2)) e1)) swapInExp e = return e
Your consent to our cookies if you continue to use this website.