Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent www.cs.kent.ac.uk/projects/refactor-fp/ Refactoring Functional Programs.

Slides:



Advertisements
Similar presentations
PROGETTO PATTERN Attività di Ricerca del gruppo di Catania nel I Anno Energy efficient solutions for connectivity and data delivery in self-organizing.
Advertisements

CPSC 388 – Compiler Design and Construction
HaRe The Haskell Refactorer Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent
Tool Support for Refactoring Functional Programs Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent
Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent Refactoring Functional Programs.
Refactoring Functional Programs Simon Thompson with Huiqing Li Claus Reinke
Progress on ‘HaRe: The Haskell Refactorer’ Huiqing Li, Claus Reinke, Simon Thompson Computing Laboratory, University of Kent Refactoring is the process.
Tools for Refactoring Functional Programs Simon Thompson with Huiqing Li Claus Reinke
An Abstract Interpretation Framework for Refactoring P. Cousot, NYU, ENS, CNRS, INRIA R. Cousot, ENS, CNRS, INRIA F. Logozzo, M. Barnett, Microsoft Research.
Using PRI Prediction to Improve ECM Effectiveness By Scott McDonald & Ken McRitchie Ottawa, Ontario, Canada Visit us at MC Countermeasures.
IAAnalyzer: Towards a Model-Driven Modeling and Analysis Framework for C ONNECT(ors) Massimo Tivoli, University of L’Aquila (UNIVAQ)
1 Status update on the CRs T2S Programme Office European Central Bank Advisory Group November 2013 ECB-PUBLIC Item 6.1.
Addressing the Challenges of Current Software. Questions to Address Why? What? Where? How?
Kathleen Fisher cs242 Reading: “A history of Haskell: Being lazy with class”,A history of Haskell: Being lazy with class Section 6.4 and Section 7 “Monads.
1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design.
Refactoring Functional Programs Claus Reinke Simon Thompson TCS Seminar, 1 October 2001.
1 CIS601: Object-Oriented Programming in C++ Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised.
Lecture 3: Topics If-then-else Operator precedence While loops Static methods Recursion.
CS 330 Programming Languages 09 / 13 / 2007 Instructor: Michael Eckmann.
The Formalisation of Haskell Refactorings Huiqing Li Simon Thompson Computing Lab, University of Kent
Refactoring Haskell Programs Huiqing Li Computing Lab, University of Kent
WRT 2007 Refactoring Functional Programs Huiqing Li Simon Thompson Computing Lab Chris Brown Claus Reinke University of Kent.
Chapter 3 Program translation1 Chapt. 3 Language Translation Syntax and Semantics Translation phases Formal translation models.
The Haskell Refactorer, HaRe, and its API Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent
Generative Programming. Generic vs Generative Generic Programming focuses on representing families of domain concepts Generic Programming focuses on representing.
Refactoring Functional Programs Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent.
CASE Tools And Their Effect On Software Quality Peter Geddis – pxg07u.
A Survey of Software Refactoring Tom Mens, Tom Tourwé
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
WorkPlace Pro Utilities.
Chapter 1 Introduction Dr. Frank Lee. 1.1 Why Study Compiler? To write more efficient code in a high-level language To provide solid foundation in parsing.
Introduction CS 3358 Data Structures. What is Computer Science? Computer Science is the study of algorithms, including their  Formal and mathematical.
Software Refactoring Part I: Introduction Bartosz Walter Advanced Object-Oriented Design Lecture 5.
1 The Software Development Process  Systems analysis  Systems design  Implementation  Testing  Documentation  Evaluation  Maintenance.
Reviewing Recent ICSE Proceedings For:.  Defining and Continuous Checking of Structural Program Dependencies  Automatic Inference of Structural Changes.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 2.
Supported by ELTE IKKK, Ericsson Hungary, in cooperation with University of Kent Erlang refactoring with relational database Anikó Víg and Tamás Nagy Supervisors:
Generative Programming. Automated Assembly Lines.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
The european ITM Task Force data structure F. Imbeaux.
Supported by ELTE IKKK, Ericsson Hungary, in cooperation with University of Kent Erlang refactoring with relational database Anikó Víg and Tamás Nagy Supervisors:
Refactoring1 Improving the structure of existing code.
Eclipse 24-Apr-17.
1 CSC/ECE 517 Fall 2010 Lec. 3 Overview of Eclipse Lectures Lecture 2 “Lecture 0” Lecture 3 1.Overview 2.Installing and Running 3.Building and Running.
1. 2 Preface In the time since the 1986 edition of this book, the world of compiler design has changed significantly 3.
Overview of Previous Lesson(s) Over View  A program must be translated into a form in which it can be executed by a computer.  The software systems.
The Software Development Process
XP New Perspectives on XML, 2 nd Edition Tutorial 7 1 TUTORIAL 7 CREATING A COMPUTATIONAL STYLESHEET.
Scalable Clone Detection and Elimination for Erlang Programs Huiqing Li, Simon Thompson University of Kent Canterbury, UK.
What am I? while b != 0 if a > b a := a − b else b := b − a return a AST == Abstract Syntax Tree.
Review of Parnas’ Criteria for Decomposing Systems into Modules Zheng Wang, Yuan Zhang Michigan State University 04/19/2002.
SEG 4110 – Advanced Software Design and Reengineering Topic T Introduction to Refactoring.
Concepts and Realization of a Diagram Editor Generator Based on Hypergraph Transformation Author: Mark Minas Presenter: Song Gu.
Refactoring1 Improving the structure of existing code.
Refactoring Agile Development Project. Lecture roadmap Refactoring Some issues to address when coding.
PROGRAMMING PRE- AND POSTCONDITIONS, INVARIANTS AND METHOD CONTRACTS B MODULE 2: SOFTWARE SYSTEMS 13 NOVEMBER 2013.
CS223: Software Engineering
FUNCTIONAL PROGRAMING AT WORK - HASKELL AND DOMAIN SPECIFIC LANGUAGES Dr. John Peterson Western State Colorado University.
1 Asstt. Prof Navjot Kaur Computer Dept PRESENTED BY.
OCR A Level F453: The function and purpose of translators Translators a. describe the need for, and use of, translators to convert source code.
CS 404Ahmed Ezzat 1 CS 404 Introduction to Compiler Design Lecture Ahmed Ezzat.
STATIC CODE ANALYSIS. OUTLINE  INTRODUCTION  BACKGROUND o REGULAR EXPRESSIONS o SYNTAX TREES o CONTROL FLOW GRAPHS  TOOLS AND THEIR WORKING  ERROR.
Lesson 06: Functions Class Participation: Class Chat:
Types for Programs and Proofs
Design by Contract Fall 2016 Version.
Overview of Eclipse Lectures
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
CSE401 Introduction to Compiler Construction
CIS601: Object-Oriented Programming in C++
Combining Compile-Time and Run-Time Components
Presentation transcript:

Huiqing Li Claus Reinke Simon Thompson Computing Lab, University of Kent Refactoring Functional Programs

Manchester 042 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> String format [] = [] format [x] = [x] format (x:xs) = (x ++ "\t") : fomrat xs

Manchester 043 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> String format [] = [] format [x] = [x] format (x:xs) = (x ++ "\t") : fomrat xs

Manchester 044 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> String format [] = [] format [x] = [x] format (x:xs) = (x ++ "\t") : format xs

Manchester 045 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> String format [] = [] format [x] = [x] format (x:xs) = (x ++ "\t") : format xs

Manchester 046 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> [String] format [] = [] format [x] = [x] format (x:xs) = (x ++ "\t") : format xs

Manchester 047 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> [String] format [] = [] format [x] = [x] format (x:xs) = (x ++ “\t") : format xs

Manchester 048 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format format :: [String] -> [String] format [] = [] format [x] = [x] format (x:xs) = (x ++ "\n") : format xs

Manchester 049 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format appNL :: [String] -> [String] appNL [] = [] appNL [x] = [x] appNL (x:xs) = (x ++ "\n") : appNL xs

Manchester 0410 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. format appNL :: [String] -> [String] appNL [] = [] appNL [x] = [x] appNL (x:xs) = (x ++ "\n") : appNL xs

Manchester 0411 Writing a program -- appNL a list of Strings, one per line table :: [String] -> String table = concat. appNL appNL :: [String] -> [String] appNL [] = [] appNL [x] = [x] appNL (x:xs) = (x ++ "\n") : appNL xs

Manchester 0412 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. appNL appNL :: [String] -> [String] appNL [] = [] appNL [x] = [x] appNL (x:xs) = (x ++ "\n") : appNL xs

Manchester 0413 Writing a program -- format a list of Strings, one per line table :: [String] -> String table = concat. appNL where appNL :: [String] -> [String] appNL [] = [] appNL [x] = [x] appNL (x:xs) = (x ++ "\n") : appNL xs

Manchester 0414 Refactoring Refactoring means changing the design of program … … without changing its behaviour. Refactoring comes in many forms micro refactoring as a part of program development, major refactoring as a preliminary to revision, as a part of debugging, … As programmers, we do it all the time.

Manchester 0415 Not just programming Paper or presentation moving sections about; amalgamate sections; move inline code to a figure; animation; … Proof introduce lemma; remove, amalgamate hypotheses, … Program the topic of the lecture

Manchester 0416 Overview of the talk Example refactorings … what do we learn? Refactoring functional programs Generalities Tooling: demo, rationale, design. What comes next? Conclusions

Manchester 0417 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 proofs that the implemented refactorings are correct. Currently mid-project: the latest HaRe release is module-aware and has module refactorings.

Manchester 0418 Refactoring functional programs Semantics: can articulate preconditions and … … verify transformations. Absence of side effects makes big changes predictable and verifiable … … unlike OO. Language support: expressive type system, abstraction mechanisms, HOFs, … Opens up other possibilities … proof …

Manchester 0419 Rename f x y = …  Name may be too specific, if the function is a candidate for reuse. findMaxVolume x y = …  Make the specific purpose of the function clearer. Needs scope information: just change this f and not all f s (e.g. local definitions or variables). Needs module information: change f wherever it is imported.

Manchester 0420 Lift / demote f x y = … h … where h = …  Hide a function which is clearly subsidiary to f ; clear up the namespace. f x y = … (h y) … h y = …  Makes h accessible to the other functions in the module and beyond. Needs free variable information: which of the parameters of f is used in the definition of h ? Need h not to be defined at the top level, …, DMR.

Manchester 0421 Lessons from the first examples Changes are not limited to a single point or even a single module: diffuse and bureaucratic … … unlike traditional program transformation. Many refactorings bidirectional … … as there is never a unique correct design.

Manchester 0422 How to apply refactoring? By hand, in a text editor 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 programmer’s toolkit.

Manchester 0423 Machine support invaluable Current practice: editor + type checker (+ tests). Our project: automated support for a repertoire of refactorings … … integrated into the existing development process: Haskell IDEs such as vim and emacs.

Manchester 0424 Demonstration of HaRe, hosted in vim.

Manchester 0425 Proof of concept … To show proof of concept it is enough to: build a stand-alone tool, work with a subset of the language, ‘pretty print’ the refactored source code in a standard format.

Manchester 0426 … or a useful tool? To make a tool that will be used we must: integrate with existing program development tools: the program editors emacs and vim: only add to their capabilities; work with the complete Haskell 98 language; preserve the formatting and comments in the refactored source code; allow users to extend and script the system.

Manchester 0427 Refactorings implemented in HaRe Rename Delete Lift (top / one level) Demote Introduce definition Remove definition Unfold Generalise Add / remove params All these refactorings are module aware. Move def between modules Delete /add to exports Clean imports Make imports explicit

Manchester 0428 The Implementation of Hare Information gathering Pre-condition checking Program transformation Program rendering

Manchester 0429 Information needed Syntax: replace the function called sq, not the variable sq …… parse tree. Static semantics: replace this function sq, not all the sq functions …… scope information. Module information: what is the traffic between this module and its clients …… call graph. Type information: replace this identifier when it is used at this type …… type annotations.

Manchester 0430 Infrastructure To achieve this we chose to: build a tool that can interoperate with emacs, vim, … yet act separately. leverage existing libraries for processing Haskell 98, for tree transformation, yet … … modify them as little as possible. be as portable as possible, in the Haskell space.

Manchester 0431 The Haskell background Libraries parser:many type checker:few tree transformations:few Difficulties Haskell98 vs. Haskell extensions. Libraries: proof of concept vs. distributable. Source code regeneration. Real project

Manchester 0432 Programatica 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 … … freely available under BSD licence.

Manchester 0433 The Implementation of Hare Information gathering Pre-condition checking Program transformation Program rendering

Manchester 0434 First steps … lifting and friends Use the Haddock parser … full Haskell given in 500 lines of data type definitions. Work by hand over the Haskell syntax: 27 cases for expressions … Code for finding free variables, for instance …

Manchester 0435 Finding free variables … 100 lines instance FreeVbls HsExp where freeVbls (HsVar v) = [v] freeVbls (HsApp f e) = freeVbls f ++ freeVbls e freeVbls (HsLambda ps e) = freeVbls e \\ concatMap paramNames ps freeVbls (HsCase exp cases) = freeVbls exp ++ concatMap freeVbls cases freeVbls (HsTuple _ es) = concatMap freeVbls es … etc.

Manchester 0436 This approach Boiler plate code … … 1000 lines for 100 lines of significant code. Error prone: significant code lost in the noise. Want to generate the boiler plate and the tree traversals … … DriFT: Winstanley, Wallace … Strafunski: Lämmel and Visser

Manchester 0437 Strafunski Strafunski allows a user to write general (read generic), type safe, tree traversing programs … … with ad hoc behaviour at particular points. Traverse through the tree accumulating free variables from component parts, except in the case of lambda abstraction, local scopes, … Strafunski allows us to work within Haskell … other options are under development.

Manchester 0438 Rename an identifier 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

Manchester 0439 The coding effort Transformations with Strafunski are straightforward … … the chore is implementing conditions that guarantee that the transformation is meaning- preserving. This is where much of our code lies.

Manchester 0440 The Implementation of Hare Information gathering Pre-condition checking Program transformation Program rendering

Manchester 0441 Program rendering example -- 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 Promote the definition of sq to top level

Manchester 0442 Program rendering 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 Using a pretty printer: comments lost and layout quite different.

Manchester 0443 Program rendering example -- 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 Promote the definition of sq to top level

Manchester 0444 Program rendering example -- 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 Layout and comments preserved.

Manchester 0445 Rendering: our approach White space and comments in the token stream. 2 views of the program: token stream and AST. Modification of the AST guides the modification of the token stream. After a refactoring, the program source is extracted from the token stream not the AST. Use heuristics to associate comments with semantic entities.

Manchester 0446 Production tool (version 0) Programatica parser and type checker Refactor using a Strafunski engine Render code from the token stream and syntax tree.

Manchester 0447 Production tool (version 1) Programatica parser and type checker Refactor using a Strafunski engine Render code from the token stream and syntax tree. Pass lexical information to update the syntax tree and so avoid reparsing

Manchester 0448 Module awareness: example Move a top-level definition f from module A to B. -- 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? -- Remove the definition of f from module A. -- Add the definition to module B. -- Modify the import/export lists in module A, B and the client modules of A and B if necessary. -- Change uses of A.f to B.f or f in all affected modules. -- Resolve ambiguity.

Manchester 0449 What have we learned? Emerging Haskell libraries make it a practical platform. Efficiency issues … type checking large systems. Limitations of IDE interactions in vim and emacs. Reflections on Haskell itself.

Manchester 0450 Reflecting on Haskell Cannot hide items in an export list (though you can on import). The formal semantics of pattern matching is problematic. ‘Ambiguity’ vs. name clash. ‘Tab’ is a nightmare! Correspondence principle fails …

Manchester 0451 Correspondence Operations on definitions and operations on expressions can be placed in correspondence (R.D.Tennent, 1980)

Manchester 0452 Correspondence Definitions where f x y = e f x | g1 = e1 | g2 = e2 Expressions let \x y -> e f x = if g1 then e1 else if g2 …

Manchester 0453 Where do we go next? Larger-scale examples: ADTs, monads, … An API for do-it-yourself refactorings, or … … a language for composing refactorings Detecting ‘bad smells’ Evolving the evidence: GC6.

Manchester 0454 What do users want? Find and remove duplicate code. Argument permutations. Data refactorings. More traditional program transformations. Monadification.

Manchester 0455 Monadification (cf Erwig) r = f e1 e2 dov1 <- e1 v2 <- e2 r <- f v1 v2 return r

Manchester 0456 Larger-scale examples More complex examples in the functional domain; often link with data types. Dawning realisation that can some refactorings are pretty powerful. Bidirectional … no right answer.

Manchester 0457 Algebraic or abstract type? data Tr a = Leaf a | Node a (Tr a) (Tr a) Tr Leaf Node flatten :: Tr a -> [a] flatten (Leaf x) = [x] flatten (Node s t) = flatten s ++ flatten t

Manchester 0458 Algebraic or abstract type? data Tr a = Leaf a | Node a (Tr a) (Tr a) isLeaf = … isNode = … … Tr isLeaf isNode leaf left right mkLeaf mkNode flatten :: Tr a -> [a] flatten t | isleaf t = [leaf t] | isNode t = flatten (left t) ++ flatten (right t)

Manchester 0459 Algebraic or abstract type?  Pattern matching syntax is more direct … … but can achieve a considerable amount with field names. Other reasons? Simplicity (due to other refactoring steps?).  Allows changes in the implementation type without affecting the client: e.g. might memoise Problematic with a primitive type as carrier. Allows an invariant to be preserved.

Manchester 0460 Outside or inside? data Tr a = Leaf a | Node a (Tr a) (Tr a) isLeaf = … … Tr isLeaf isNode leaf left right mkLeaf mkNode flatten :: Tr a -> [a] flatten t | isleaf t = [leaf t] | isNode t = flatten (left t) ++ flatten (right t)

Manchester 0461 Outside or inside? data Tr a = Leaf a | Node a (Tr a) (Tr a) isLeaf = … … flatten = … Tr isLeaf isNode leaf left right mkLeaf mkNode flatten

Manchester 0462 Outside or inside?  If inside and the type is reimplemented, need to reimplement everything in the signature, including flatten. The more outside the better, therefore.  If inside can modify the implementation to memoise values of flatten, or to give a better implementation using the concrete type. Layered types possible: put the utilities in a privileged zone.

Manchester 0463 API Refactorings Refactoring utilities Strafunski Haskell

Manchester 0464 DSL Refactorings Refactoring utilities Strafunski Haskell Combining forms

Manchester 0465 Detecting ‘bad smells’ Work by Chris Ryder

Manchester 0466 Evolving the evidence Dependable System Evolution is the software engineering grand challenge. Build systems with evidence of their dependability … … but this begs the question of how to evolve the evidence in line with the system. Refactoring proofs, test coverage data etc.

Manchester 0467 Teaching and learning design Exciting prospect of using a refactoring tool as an integral part of an elementary programming course. Learning a language: learn how you could modify the programs that you have written … … appreciate the design space, and … the features of the language.

Manchester 0468 Conclusions Refactoring + functional programming: good fit. Practical tool … not ‘yet another type tweak’. Leverage from available libraries … with work. We have begun to use the tool in building itself! Much more to do than we have time for. Martin Fowler’s ‘Rubicon’: ‘extract definition’ … in HaRe version 1 … fp productivity.