Mars: an Imperative/Declarative Higher-Order Programming Language with Automatic Destructive Update
Total Page:16
File Type:pdf, Size:1020Kb
Mars An Imperative/Declarative Higher-Order Programming Language With Automatic Destructive Update Matthew Giuca Submitted in total fulfilment of the requirements of the degree of Doctor of Philosophy July 2014 Department of Computing and Information Systems The University of Melbourne i Abstract For years, we have enjoyed the robustness of programming without side-effects in lan- guages such as Haskell and Mercury. Yet in order to use languages with true referential transparency, we seem to have to give up basic imperative constructs that we have be- come accustomed to: looping constructs, variable update, destructive update of arrays, and so on. In this thesis, we explore the design of programming languages which com- bine the benefits of referential transparency with imperative-style programming. First, we present a framework for classifying programming languages according to the benefits of pure programming. Our definition applies to a wider range of languages than common terms such as “declarative” and “pure,” capturing the specific benefit of prohibiting global side-effects, without ruling out imperative programming languages. Second, we present the design and implementation for a new programming language, Mars, which allows the programmer to write imperative-style code using Python syntax, yet has the benefits of a language with referential transparency. The design philosophy behind the language, and its future directions, are discussed. Third, we note the tendency for imperative programs to use array update operations, which are very slow in a naïve implementation of any language such as Mars. We explore static analyses for automatically converting slow array copying code into fast destructive update instructions, and present the design and implementation of an optimiser for Mars, which improves on previous work by precisely handling higher-order functions, includ- ing those that both accept and return functions. The sum of this work is an efficient im- perative language with the demonstrable software engineering benefit of non-interfering functions. ii Declaration This is to certify that: (i) the thesis comprises only my original work towards the Ph.D. except where indi- cated in the Preface, (ii) due acknowledgement has been made in the text to all other material used, (iii) the thesis is fewer than 100,000 words in length, exclusive of tables, maps, bibliogra- phies and appendices. Matthew Laurence Giuca Department of Computing and Information Systems The University of Melbourne July 2014 iii Preface Drafts of Chapter 3 were written in collaboration with Dr. Peter Schachte (my Ph.D. supervisor), with the intention of publishing as a separate conference paper. The text was originally my own work, and after our collaboration, the chapter was edited heavily by myself. iv Acknowledgements Six years is a non-trivial amount of time to spend on any project, and so I have a long list of people to thank for their support and assistance. First, and foremost, I wish to thank my supervisor, Dr. Peter Schachte, for his support throughout my candidature. From the weekly insightful (and often lengthy) discussions in his office, to an ongoing email support line long after I officially left the university, Peter has always been a source of good ideas, helpful advice, and encouragement. I would also like to thank my advisory committee, Dr. Harald Søndergaard and Dr. Bernard Pope: in particular, Harald for his detailed feedback and help with Chapter 1, and Bernie for his many helpful comments and suggestions on earlier drafts of Chapter 3. I also thank the other research staff in what was the Department of Computer Science and Software Engineering during my time there, for their attendance at my talks and ongoing interest in my research. In particular, Dr. Lee Naish deserves credit for proof-reading my thesis, and pointing out the polymorphic recursion problem discussed in Section 9.6.3. I would also like to thank my two examiners, who provided many pages of detailed notes on the thesis, with thoughtful comments and suggestions. I thank my parents, Anne and Vince, and my brothers, David and Dominic, for their support. Of course, I must also thank my amazing partner, Shanika Kuruppu, who started this journey with me, and who encouraged me and waited patiently while I worked through the weekends. I would not have completed this work without Shani’s continual love and support. Finally, I would like to thank the Australian Department of Education for funding the first three and a half years of my candidature. Contents List of Figures ix 1 Introduction 1 1.1 A purely imperative programming language . .2 1.2 Automatic destructive update . .4 1.3 Contributions . .7 1.4 Conventions in this thesis . .8 1.5 Terminology . .9 1.6 Preliminaries . 10 1.7 Outline of the thesis . 17 2 Survey of hybrid imperative/declarative languages 19 2.1 Introduction . 19 2.2 Imperative languages with functional features . 23 2.3 Imperative languages with purity constraints . 24 2.4 Declarative languages with imperative constructs . 26 2.5 Languages with explicit effect annotations . 31 2.6 Conclusion . 33 3 Interface integrity 35 3.1 Introduction . 35 3.2 Interface integrity . 38 3.3 Interface integrity and language features . 43 3.4 Comparison to related concepts . 52 3.5 Language construction . 53 3.6 Conclusion . 59 4 Mars: An imperative/declarative language 61 v vi CONTENTS 4.1 Introduction . 61 4.2 Overview . 62 4.3 Standard libraries . 74 4.4 Example . 75 4.5 Conclusion . 77 5 Code representation for analysis 79 5.1 Introduction . 79 5.2 Converting Mars to MIR . 80 5.3 Converting other languages to MIR . 89 5.4 The implementation of MIR . 93 5.5 Abstract syntax . 95 5.6 Concrete value denotational semantics . 96 5.7 Concrete memory denotational semantics . 103 5.8 Conclusion . 108 6 Abstract interpretation 111 6.1 Introduction . 111 6.2 The abstract domain . 113 6.3 Abstraction and concretisation . 116 6.4 Abstract semantics . 119 6.5 Making use of the semantics . 122 6.6 Condensing semantics and context-insensitive analysis . 125 6.7 Efficient bottom-up analysis . 128 6.8 Conclusion . 131 7 Existing sharing and reuse analyses 133 7.1 Introduction . 133 7.2 Runtime reference counting . 134 7.3 Type-based approaches . 134 7.4 Compile-time garbage collection . 140 7.5 Dynamic memory reuse flags . 151 7.6 Aliasing analysis for impure and unsafe languages . 152 7.7 Dynamic aliasing analysis . 155 7.8 Static pointer nullification . 156 7.9 Conclusion . 157 8 First-order uniqueness inference 159 CONTENTS vii 8.1 Introduction . 159 8.2 Motivating examples . 160 8.3 Abstract memory denotational semantics . 174 8.4 Comparison to Mercury’s CTGC system . 189 8.5 Conclusion . 190 9 Higher-order uniqueness inference 191 9.1 Introduction . 191 9.2 Why analyse higher-order? . 192 9.3 Overview . 196 9.4 The upward higher-order problem . 199 9.5 The non-applicative downward higher-order problem . 205 9.6 The applicative downward higher-order problem . 208 9.7 Abstract memory denotational semantics . 218 9.8 Algebraic analysis . 227 9.9 Analysing non-Mars language features . 236 9.10 Conclusion . 239 10 Destructive update optimisation 241 10.1 Introduction . 241 10.2 Live-variable analysis . 242 10.3 Call mode selection . 245 10.4 Dynamic call mode vectors . 253 10.5 Multiple specialisation . 257 10.6 Higher-order call modes . 261 10.7 Structure reuse . 262 10.8 Future work . 270 10.9 Conclusion . 271 11 Conclusion 273 11.1 A pure imperative programming language . 273 11.2 Automatic destructive update . 275 11.3 Benchmarks . 276 11.4 Future work . 279 11.5 What we have built . 280 viii CONTENTS List of Figures 1.1 Linked list of boxed numbers, showing the meaning of various terms . 10 1.2 Hasse diagram for the partial order }(f0, 1g) ................. 14 3.1 Example function declaration and call syntax . 40 3.2 Effective interface (pure) . 41 3.3 Effective interface (with ref) . 42 3.4 Unintended aliasing of the player and rocket position ............ 47 3.5 The denotational semantics for L0 ........................ 54 3.6 Additions to the denotational semantics for L1 ................ 56 3.7 Additions to the denotational semantics for L2 ................ 57 3.8 Additions to the denotational semantics for L3 ................ 58 6.1 Hasse diagram for the domain f(0), (−), (+), (±)g ............. 111 6.2 Hasse diagram for the domain }(fNil, Two, Threeg) ............. 115 6.3 Call graph with.