University of Southampton Research Repository Eprints Soton
Total Page:16
File Type:pdf, Size:1020Kb
University of Southampton Research Repository ePrints Soton Copyright © and Moral Rights for this thesis are retained by the author and/or other copyright owners. A copy can be downloaded for personal non-commercial research or study, without prior permission or charge. This thesis cannot be reproduced or quoted extensively from without first obtaining permission in writing from the copyright holder/s. The content must not be changed in any way or sold commercially in any format or medium without the formal permission of the copyright holders. When referring to this work, full bibliographic details including the author, title, awarding institution and date of the thesis must be given e.g. AUTHOR (year of submission) "Full thesis title", University of Southampton, name of the University School or Department, PhD Thesis, pagination http://eprints.soton.ac.uk UNIVERSITY OF SOUTHAMPTON FACULTY OF PHYSICAL SCIENCES AND ENGINEERING Electronics and Computer Science Preemptive type checking in dynamically typed programs by Neville Grech Thesis for the degree of Doctor of Philosophy November 2013 The research work disclosed in this publication is partially funded by the Strategic Educational Pathways Scholarship (Malta). This Scholarship is part-financed by the European Union – European Social Fund (ESF) under Operational Programme II – Cohesion Policy 2007-2013, “Empowering People for More Jobs and a Better Quality Of Life”. Operational Programme II – Cohesion Policy 2007-2013 Empowering People for More Jobs and a Better Quality of Life Scholarship part-financed by the European Union European Social Fund (ESF) Co-financing rate: 85% EU Funds; 15%National Funds Investing in your future UNIVERSITY OF SOUTHAMPTON ABSTRACT FACULTY OF PHYSICAL SCIENCES AND ENGINEERING Electronics and Computer Science Doctor of Philosophy PREEMPTIVE TYPE CHECKING IN DYNAMICALLY TYPED PROGRAMS by Neville Grech With the rise of languages such as JavaScript, dynamically typed languages have gained a strong foothold in the programming language landscape. These languages are very well suited for rapid prototyping and for use with agile programming methodologies. However, programmers would benefit from the ability to detect type errors in their code early, without imposing unnecessary restrictions on their programs. Here we describe a new type inference system that identifies potential type errors through a flow-sensitive static analysis. This analysis is invoked at a very late stage, after the compilation to bytecode and initialisation of the program. It computes for every expression the variable’s present (from the values that it has last been assigned) and future (with which it is used in the further program execution) types, respectively. Using this information, our mechanism inserts type checks at strategic points in the original program. We prove that these checks, inserted as early as possible, preempt type errors earlier than existing type systems. We further show that these checks do not change the semantics of programs that do not raise type errors. Preemptive type checking can be added to existing languages without the need to modify the existing runtime environment. We show this with an implementation for the Python language and demonstrate its effectiveness on a number of benchmarks. Contents Declaration of Authorship xi Acknowledgements xiii 1 Introduction1 1.1 Dynamically typed languages...........................5 1.2 Problem statement................................6 1.3 Research objectives................................8 1.4 Overview of approach...............................9 1.5 Original Contributions.............................. 11 1.6 Outline...................................... 13 2 Background and literature review 15 2.1 Types....................................... 15 2.1.1 Simply typed lambda calculus...................... 16 2.1.2 Subtyping................................. 17 2.1.3 Kinds of type systems.......................... 18 2.1.4 Fixed Points............................... 21 2.2 Compiling dynamically typed programs..................... 22 2.2.1 Partial evaluation............................. 22 2.2.2 Tracing JIT compilation......................... 23 2.3 Gradual type systems............................... 24 2.3.1 Dynamic types.............................. 25 2.3.2 Usage and evaluation........................... 26 2.4 Soft typing.................................... 27 2.5 Static type inference for dynamically typed languages.............. 29 2.6 Control flow analysis............................... 32 2.7 Summary..................................... 33 3 The µPython language 35 3.1 µPython source code............................... 35 3.2 µPython bytecode................................. 37 3.3 Compiling and running µPython......................... 38 3.4 Example...................................... 39 3.5 Relationship to Python 3.3............................ 42 3.6 Conclusion.................................... 43 4 Type inference for µPython 45 vii viii CONTENTS 4.1 Types....................................... 45 4.2 Program execution points............................. 47 4.3 Type inference................................... 49 4.4 Type inference rules and trails.......................... 51 4.5 Termination of type inference algorithm..................... 55 4.6 Soundness for present types............................ 56 4.7 Soundness for future use types.......................... 63 4.8 Type inference examples............................. 70 4.9 Conclusion.................................... 71 5 Type checking and assertion insertion 73 5.1 Checked µPython semantics........................... 73 5.2 Maintaining error preserving simulations..................... 75 5.3 Optimality..................................... 79 5.4 Type check insertions............................... 82 5.5 A worked example................................ 84 5.6 Conclusion.................................... 86 6 From µPython to full Python 87 6.1 Introduction.................................... 87 6.2 Architecture of the tool.............................. 88 6.3 Using the type checker on existing programs................... 89 6.4 Control flow analysis............................... 94 6.5 Type analysis................................... 96 6.6 Modelling a stack................................. 97 6.7 Type check insertion............................... 98 6.8 Variables of interest at each point......................... 102 6.9 Experiments.................................... 104 6.9.1 Synthetic examples............................ 104 6.9.2 Real world benchmarks.......................... 108 6.10 Results....................................... 114 6.11 Conclusions.................................... 117 7 Conclusion and Future work 119 7.1 Main contributions................................ 119 7.2 Future work directions.............................. 120 7.3 Concluding Remarks............................... 125 References 127 Implementation listing 135 List of Figures 1.1 Dynamically typed program with type errors...................1 1.2 Modified main function..............................3 1.3 Transformed version of the compute function..................4 1.4 Phases of the type checking process........................ 12 2.1 Typing rules for the simply typed lambda calculus................ 17 2.2 Constraints introduced for the simply typed lambda calculus........... 17 2.3 Classifications of some common programming languages [21]......... 19 3.1 Syntax of the µPython language......................... 36 3.2 The µPython bytecodes.............................. 37 3.3 µPython compiler................................. 39 3.4 Semantics of the µPython Bytecode....................... 40 3.5 A simple µPython example............................ 40 4.1 Type lattice.................................... 47 4.2 Correspondence between stacks and execution points............... 49 4.3 Inference rules for the `p judgement (axioms)................... 51 4.4 Inference rules for the `p judgement........................ 52 4.5 Inference rules for the `f judgement (axioms).................. 53 4.6 Inference rules for the `f judgement........................ 54 4.7 Functions can redefine themselves........................ 70 4.8 Simple recursion................................. 70 4.9 Mutual recursion................................. 70 4.10 Analysing this example requires going around the loop several times....... 71 5.1 Syntax of checked states............................. 75 5.2 Algorithm for inserting type checks in µPython programs............ 83 5.3 Macros for type checking insertions........................ 84 5.4 Control Flow for the µPython example...................... 85 5.5 Derivations of present and future use types.................... 85 5.6 The transformed µPython example with preemptive type checking........ 86 6.1 Phases of the type checking process, outlined in the user code.......... 89 6.2 Outline of type checking process.......................... 90 6.3 Conceptual structure................................ 91 6.4 Instantiation and interaction of instruction objects................. 93 6.5 Algorithm for constructing the intra-procedural control flow graph....... 95 6.6 Type check insertion algorithm........................... 99 ix x LIST OF FIGURES 6.7 Algorithm for emitting the bytecode........................ 100 6.8 Bytecode for the specialised main function.................... 101 6.9 Bytecode for the specialised compute function................