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

Slides:



Advertisements
Similar presentations
Numbers Treasure Hunt Following each question, click on the answer. If correct, the next page will load with a graphic first – these can be used to check.
Advertisements

Repaso: Unidad 2 Lección 2
1 A B C
Simplifications of Context-Free Grammars
Variations of the Turing Machine
Angstrom Care 培苗社 Quadratic Equation II
AP STUDY SESSION 2.
1
Select from the most commonly used minutes below.
Chapter 7 System Models.
Copyright © 2003 Pearson Education, Inc. Slide 1 Computer Systems Organization & Architecture Chapters 8-12 John D. Carpinelli.
David Burdett May 11, 2004 Package Binding for WS CDL.
Local Customization Chapter 2. Local Customization 2-2 Objectives Customization Considerations Types of Data Elements Location for Locally Defined Data.
Create an Application Title 1Y - Youth Chapter 5.
Process a Customer Chapter 2. Process a Customer 2-2 Objectives Understand what defines a Customer Learn how to check for an existing Customer Learn how.
Custom Statutory Programs Chapter 3. Customary Statutory Programs and Titles 3-2 Objectives Add Local Statutory Programs Create Customer Application For.
CALENDAR.
1 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt BlendsDigraphsShort.
Programming Language Concepts
1 Click here to End Presentation Software: Installation and Updates Internet Download CD release NACIS Updates.
The 5S numbers game..
Media-Monitoring Final Report April - May 2010 News.
Break Time Remaining 10:00.
Factoring Quadratics — ax² + bx + c Topic
Turing Machines.
Anything But Typical Learning to Love JavaScript Prototypes Page 1 © 2010 Razorfish. All rights reserved. Dan Nichols March 14, 2010.
Table 12.1: Cash Flows to a Cash and Carry Trading Strategy.
PP Test Review Sections 6-1 to 6-6
Bellwork Do the following problem on a ½ sheet of paper and turn in.
CS 6143 COMPUTER ARCHITECTURE II SPRING 2014 ACM Principles and Practice of Parallel Programming, PPoPP, 2006 Panel Presentations Parallel Processing is.
Operating Systems Operating Systems - Winter 2010 Chapter 3 – Input/Output Vrije Universiteit Amsterdam.
Exarte Bezoek aan de Mediacampus Bachelor in de grafische en digitale media April 2014.
Lexical Analysis Arial Font Family.
Copyright © 2012, Elsevier Inc. All rights Reserved. 1 Chapter 7 Modeling Structure with Blocks.
GIS Lecture 8 Spatial Data Processing.
Tool Support for Refactoring Functional Programs Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent
Adding Up In Chunks.
Progress on ‘HaRe: The Haskell Refactorer’ Huiqing Li, Claus Reinke, Simon Thompson Computing Laboratory, University of Kent Refactoring is the process.
FAFSA on the Web Preview Presentation December 2013.
MaK_Full ahead loaded 1 Alarm Page Directory (F11)
1 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt 10 pt 15 pt 20 pt 25 pt 5 pt Synthetic.
Artificial Intelligence
Before Between After.
: 3 00.
5 minutes.
1 Non Deterministic Automata. 2 Alphabet = Nondeterministic Finite Accepter (NFA)
1 hi at no doifpi me be go we of at be do go hi if me no of pi we Inorder Traversal Inorder traversal. n Visit the left subtree. n Visit the node. n Visit.
1 Let’s Recapitulate. 2 Regular Languages DFAs NFAs Regular Expressions Regular Grammars.
Types of selection structures
Speak Up for Safety Dr. Susan Strauss Harassment & Bullying Consultant November 9, 2012.
1 Titre de la diapositive SDMO Industries – Training Département MICS KERYS 09- MICS KERYS – WEBSITE.
Essential Cell Biology
Converting a Fraction to %
Numerical Analysis 1 EE, NCKU Tien-Hao Chang (Darby Chang)
Clock will move after 1 minute
PSSA Preparation.
Physics for Scientists & Engineers, 3rd Edition
Select a time to count down from the clock above
Copyright Tim Morris/St Stephen's School
1.step PMIT start + initial project data input Concept Concept.
1 Dr. Scott Schaefer Least Squares Curves, Rational Representations, Splines and Continuity.
User Defined Functions Lesson 1 CS1313 Fall User Defined Functions 1 Outline 1.User Defined Functions 1 Outline 2.Standard Library Not Enough #1.
1 Decidability continued…. 2 Theorem: For a recursively enumerable language it is undecidable to determine whether is finite Proof: We will reduce the.
1 Non Deterministic Automata. 2 Alphabet = Nondeterministic Finite Accepter (NFA)
The Formalisation of Haskell Refactorings Huiqing Li Simon Thompson Computing Lab, University of Kent
Refactoring Haskell Programs Huiqing Li Computing Lab, University of Kent
The Haskell Refactorer, HaRe, and its API Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent
Presentation transcript:

HaRe The Haskell Refactorer Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent

2 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

3 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

4 Refactoring What? Changing the structure of existing code … … without changing its meaning. Essential part of the functional programming process. Where? Development, maintenance, … -- to make the code easier to understand and modify -- to improve code reuse, quality and productivity. Not just programming … also proof, presentation, …

5 A Simple Example module Main where pow = 2 f [] = 0 f (h:t) = h^pow + f t main = print $ f [1..4] The original code Refactoring 1: rename f to sumSquares to make the purpose of the function clearer.

6 A Simple Example (cont.) Code after renaming Refactoring 2: demote the definition of pow to make its scope narrower. module Main where pow = 2 sumSquares [] = 0 sumSquares (h:t) = h^pow + sumSquares t main = print $ sumSquares [1..4]

7 A Simple Example (cont.) module Main where sumSquares [] = 0 sumSquares (h:t) = h^pow + sumSquares t where pow = 2 main = print $ sumSquares [1..4] Code after demoting

8 Refactoring vs Program Optimisation Refactoring -- source-to-source -- functionality-preserving -- improve the design of a program -- diffuse and bureaucratic -- bi-directional Program optimisation -- source-to-source -- functionality-preserving -- improve the efficiency of a program -- focused -- unidirectional

9 How to apply refactoring? By hand Tedious Error-prone Depends on extensive testing With machine support Reliable Low cost: easy to make and un-make large changes Exploratory: a full part of the programmers’ toolkit

10 Refactoring Functional Programs 3-year EPSRC-funded project  Explore the prospects of refactoring functional programs  Catalogue useful refactorings  Look into the difference between OO and FP refactoring  A real life refactoring tool for Haskell programming  A formal way to specify refactorings, and a set of formal proofs that the implemented refactorings are correct. Currently end of second year: the second HaRe is module-aware.

11 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

12 HaRe – The Haskell Refactorer -- A prototype tool for refactoring Haskell programs -- Driving concerns: usability and solid basis for extensions. -- Implemented in Haskell, using Programatica’s frontends and Strafunski’s generic programming technique. -- Full Haskell 98 coverage -- Integrated with the two program editors: Emacs and Vim -- Preserves both comments and layout style of the source

13 Refactorings in HaRe: Move Definition e.g. demote/promote the definition of f module Main where f [] = 0 f (h:t) = h^2 + f t main = print $ f [1..4] module Main where main = print $ f [1..4] where f [] = 0 f (h:t) = h^2 + f t Move a definition --Demote a definition: move a definition down in the scope hierarchy to make its scope narrower. --Promote a definition: move a definition up in the scope hierarchy to widen its scope.

14 Refactorings in HaRe: Generalise module Main where f [] = 0 f (h:t) = h^2 + f t main = f [1..4] => e.g. generalise definition f on sub-expression 0 with new parameter name n. module Main where f n [] = n f n (h:t) = h^2 + f n t main = f 0 [1..4] Generalise a definition -- select a sub-expression of the rhs of the definition and introduce that sub-expression as a new argument to the function at each of its call sites.

15 Refactorings in HaRe … others Released: Rename Introduce definition unfold Duplicate definition Delete definition Add/Remove an argument Not yet released: Move definition to another module Clean imports Make imports explicit Add/Remove entity to/from exports From algebraic data type to ADT (in progress)

16 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe (hosted in Emacs) The Implementation of HaRe Current Work Future Work

17 Demo module Demo(sumSquares) where sq x = x ^ 2 sumSquares [] = 0 sumSquares (x:xs) = sq x + sumSquares xs anotherFun = sumSquares [1..4]

18 Generalise Definition module Demo(sumSquares) where sq x = x ^ 2 sumSquares [] = 0 sumSquares (x:xs) = sq x + sumSquares xs anotherFun = sumSquares [1..4]

19 Generalise Definition module Demo(sumSquares) where sq x = x ^ 2 sumSquares [] = 0 sumSquares (x:xs) = sq x + sumSquares xs anotherFun = sumSquares [1..4] name of new parameter?

20 Generalise Definition module Demo(sumSquares) where sq x = x ^ 2 sumSquares [] = 0 sumSquares (x:xs) = sq x + sumSquares xs anotherFun = sumSquares [1..4] name of new parameter? f

21 Generalise Definition module Demo(sumSquares, sumSquares_gen) where sq x = x ^ 2 sumSquares f [] = 0 sumSquares f (x:xs) = f x + sumSquares f xs sumSquares_gen = sq anotherFun = sumSquares sq [1..4]

22 Generalise Definition module DemoMain where import Demo ints = [1..10] main = print $ sumSquares ints

23 Generalise Definition module DemoMain where import Demo ints = [1..10] main = print $ sumSquares sumSquares_gen ints

24 Move definition to another module module DemoMain where import Demo ints = [1..10] main = print $ sumSquares sumSquares_gen ints Destination module name?

25 Move definition to another module module DemoMain where import Demo ints = [1..10] main = print $ sumSquares sumSquares_gen ints Destination module name? Demo

26 Move definition to another module module DemoMain where import Demo main = print $ sumSquares sumSquares_gen ints module Demo(ints,sumSquares, sumSquares_gen) where ints = [1..10] sq x = x ^ 2 sumSquares f [] = 0 sumSquares f (x:xs) = f x + sumSquares f xs sumSquares_gen = sq anotherFun = sumSquares sq [1..4]

27 Demo end

28 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

29 The Implementation of HaRe An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq x + sq y where sq :: Int->Int sq x = x ^ pow pow = 2 :: Int main = sumSquares 10 20

30 The Implementation of HaRe Step 1 : Identify the definition to be promoted. An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq x + sq y where sq :: Int->Int sq x = x ^ pow pow = 2 :: Int main = sumSquares 10 20

31 The Implementation of HaRe Step 2: Is sq defined at top level here or in importing modules? Is sq imported from other modules? An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq x + sq y where sq :: Int->Int sq x = x ^ pow pow = 2 :: Int main = sumSquares 10 20

32 The Implementation of HaRe Step 3: does sq use any identifiers locally defined in sumSquares? An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq x + sq y where sq :: Int->Int sq x = x ^ pow pow = 2 :: Int main = sumSquares 10 20

33 The Implementation of HaRe Step 4: If so, generalise to add these parameters and change type signature. An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq pow x + sq pow y where sq :: Int->Int->Int sq pow x = x ^ pow pow = 2 :: Int main = sumSquares 10 20

34 The Implementation of HaRe Step 5: Move sq to top level. An example: Promote the definition of sq to top level. -- This is an example module Main where sumSquares x y = sq pow x + sq pow y where pow = 2 :: Int sq :: Int->Int->Int sq pow x = x ^ pow main = sumSquares 10 20

35 The Implementation of HaRe Information gathering Pre-condition checking Program rendering Program transformation Basic steps

36 The Implementation of HaRe Information gathering Pre-condition checking Program rendering Program transformation Basic steps

37 The Implementation of HaRe Information required -- Abstract Syntax Tree (AST): for finding syntax phrases, e.g. the definition of sq. (need parser & lexer) -- Static semantics: for the scope of identifiers. -- Type information: for type-aware refactorings. (need type-checker) -- Module information: for module-aware refactorings. (need module analysis system)

38 Project at OGI to build a Haskell system … … with integral support for verification at various levels: assertion, testing, proof etc. The Programatica project has built a Haskell front end in Haskell, supporting syntax, static, type and module analysis, and a lexer that preserves location info. … freely available under BSD licence.

39 The Implementation of HaRe Information gathering Pre-condition checking Program rendering Program transformation Basic steps

40 The Implementation of HaRe -- Our initial experience -- A large amount of boilerplate code for each refactoring -- Tiresome to write and error prone. -- Why? -- The large size of the Haskell grammar: about 20 algebraic data types and the sum of 110 data constructors. -- Both program analysis and transformation involve traversing the syntax tree frequently. Pre-condition checking and program transformation

41 The Implementation of HaRe Example: code for renaming an identifier instance Rename HsExp where rename oldName newName (Exp (HsId id)) = Exp (HsId (rename oldName newName id)) rename oldName newName (Exp (HsLit x)) = Exp(HsLit x) rename oldName newName (Exp (HsInfixApp e1 op e2)) = Exp (HsInfixApp (rename oldName newName e1) (rename oldName newName op) (rename oldName newName e2)) rename oldName newName (Exp (HsApp f e)) = Exp (HsApp (rename oldName newName f) (rename oldName newName e)) rename oldName newName (Exp(HsNegApp e)) = Exp (HsNegApp (rename oldName newName e)) rename oldName newName (Exp(HsLambda ps e)) =Exp (HsLambda (rename oldName newName ps) (rename oldName newName e))... (about 200 lines)

42 Programatica’s support for generic programming -- A small selection of generic traversal operators. -- Defined as type class instances level scheme data type definitions. -- Sensitive to changes in grammars or traversals. The Implementation of HaRe

43 Strafunski’s support for generic programming -- A Haskell library developed for supporting generic programming in application areas that involve term traversal over large ASTs. -- Allow users to write generic function that can traverse into terms with ad hoc behaviour at particular points. -- Offers a strategy combinator library StrategyLib and a pre-processor based on DrIFT. The Implementation of HaRe DrIFT – a generative tool. … Strafunski: Lämmel and Visser … DriFT: Winstanley, Wallace

44 Example: renaming an identifier using Strafunski rename:: (Term t)=>PName->HsName->t->Maybe t rename oldName newName = applyTP worker where worker = full_tdTP (idTP ‘adhocTP‘ idSite) idSite :: PName -> Maybe PName idSite name orig) | v == oldName = return (PN newName orig) idSite pn = return pn The Implementation of HaRe

45 Our experience of using Strafunski -- Traversal combinators are extensively used during the development of refactorings. -- Strafunski-style of programming makes the code concise. (average 200 lines per primitive refactoring). Much of the code lies on comment&layout preservation. -- A combinator which combines TP(type-preserving) and TU(type-unifying) would be helpful. -- Generic zipping is helpful too. (supported by the boilerplate approach). The Implementation of HaRe

46 The Implementation of HaRe Information gathering Pre-condition checking Program rendering Program transformation Basic steps

47 -- A real-life useful refactoring tool should preserve program layout and comments. but, -- layout information and comments are not preserved in AST -- the layout produced by pretty-printer may not be satisfactory and comments are still missing Program rendering The Implementation of HaRe

48 Program rendering -- example The Implementation of HaRe -- This is an example module Main where sumSquares x y = sq x + sq y where sq :: Int->Int sq x = x ^ pow pow = 2 :: Int main = print $ sumSquares program source before promoting definition sq to top level.

49 Program rendering -- example The Implementation of HaRe module Main where sumSquares x y = sq pow x + sq pow y where pow = 2 :: Int sq :: Int->Int->Int sq pow x = x ^ pow main = print $ sumSquares program source from pretty printer after promoting.

50 Program rendering -- example The Implementation of HaRe -- program source using our approach after promoting. -- This is an example module Main where sumSquares x y = sq pow x + sq pow y where pow = 2 :: Int sq :: Int->Int->Int sq pow x = x ^ pow main = print $ sumSquares 10 20

51 -- make use of the white space & comments in the token stream (the lexer output) -- the refactorer takes two views of the program: the token stream and the AST -- the modification in the AST guides the modification of the token stream. -- after a refactoring, the program source is extracted from the token stream instead of from the AST -- use heuristics for associating comments and semantics entities. Program rendering -- our approach The Implementation of HaRe

52 The current implementation architecture The Implementation of HaRe PS: program source ; TS: token stream; AAST: annotated abstract syntax tree; MI: module information ; Programatica (lexer, parser, type checker, module analysis) TS AAST + MI PS TS analysis and transformation using Strafunski AAST extract program from token stream PS

53 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

54 -- A refactoring may have effects in several modules -- Effects and constraints can be subtle, choices have to be made. -- A refactoring succeeds only if it succeeds on all affected modules in the project. -- Built on top of Programatica’s module analysis system -- Information needed: module graph, entities imported by a module, entities exported by a module -- What if the module is used by modules outside the project? Notify the user or create a wrapper? Making refactorings module-aware

55 Making refactorings module-aware Example: move a top-level definition f from module A to B. -- Conditions: -- Is f defined at the top-level of B? -- Are the free variables in f accessible within module B? -- Will the move require recursive modules? -- The transformation: -- Remove the definition of f from module A. -- Add the definition to module B. -- Modify the import/export in module A, B and the client modules of A and B if necessary. -- Change the uses of A.f to B.f or f in all affected modules. -- Resolve ambiguity.

56 From Algebraic Data Type to ADT A large-scale refactoring. Can be decomposed into a series of primitive refactorings: -- Introduce field labels -- Create discriminators -- Create constructors -- Remove nested patterns -- Remove patterns -- Move a set of declarations to a new module Need to compose primitive refactorings into one composite refactoring.

57 Outline Introduction HaRe: The Haskell Refactorer Demo of HaRe The Implementation of HaRe Current Work Future Work

58 -- Other kinds of refactorings: type-aware, interface, structural, … -- ‘Not quite refactorings’ and transformations … -- An API for do-it-yourself refactoring. -- A language for composing refactorings. -- More complex interactions between the refactorer and the user. -- Use HaRe in teaching. Future work