
ABSTRACT Title of dissertation: TYPE CHECKING AND INFERENCE FOR DYNAMIC LANGUAGES Brianna Ren Doctor of Philosophy, 2019 Dissertation directed by: Professor Jeffrey S. Foster Department of Computer Science Object-oriented dynamic languages such as Ruby, Python, and JavaScript provide rapid code development and a high degree of flexibility and agility to the programmer. Some of the their main features include dynamic typing and metapro- gramming. In dynamic typing, programmers do not declare or cast types, and types are not known until run time. In addition, an object's suitability is determined by its methods, as opposed to its class. Metaprogramming dynamically generates code as the program executes, which means that methods and classes can be added and modified at run-time. These features are powerful but lead to a major drawback of dynamic languages: the lack of static types means that type errors can remain latent long into the software development process or even into deployment, especially in the presence of metaprogramming. To bring the benefits of static types to dynamic languages, I present three pieces of work. First, I present the Ruby Type Checker (rtc), a tool that adds type check- ing to Ruby. Rtc addresses the issue of latent type errors by checking all types during run time at method entrance and exit. Thus it checks types later than a purely static system, but earlier than a traditional dynamic type system. Rtc is implemented as a Ruby library and supports type annotations on classes, methods, and objects. Rtc provides a rich type language that includes union and intersec- tion types, higher-order (block) types, and parametric polymorphism, among other features. We applied rtc to several apps and found it effective at checking types. Second, I present Hummingbird, a just-in-time static type checker for dy- namic languages. Hummingbird also prevents latent type errors, and type checks Ruby code even in the presence of metaprogramming, which is not handled by rtc. In Hummingbird, method type signatures are gathered dynamically at run-time, as those methods are created. When a method is called, Hummingbird statically type checks the method body against current type signatures. Thus, Hummingbird pro- vides thorough static checks on a per-method basis, while also allowing arbitrarily complex metaprogramming. We applied Hummingbird to six apps, including three that use Ruby on Rails, a powerful framework that relies heavily on metaprogram- ming. We found that all apps type check successfully using Hummingbird, and that Hummingbird's performance overhead is reasonable. Lastly, I present a practical type inference system for Ruby. Although both rtc and Hummingbird are very effective tools for type checking, the programmer must provide the type annotations on the application methods, which may be a time-consuming and error-prone process. Type inference is a generalization of type checking that automatically infers types while performing checking. However, stan- dard type inference often infers types that are overly permissive compared to what a programmer might write, or contain no useful information, such as the bottom type. I first present a standard type inference system for Ruby, where constraints on a method is statically gathered as soon as the method is invoked at run-time, and types are resolved after all constraints have been gathered on all methods. I then build a practical type inference system on top of the standard type inference system. The goal of my practical type inference system is to infer types that are concise and include actual classes when appropriate. Finally, I evaluate my practical type inference system on three Ruby apps and show it to be very effective compared to the standard type inference system. In sum, I believe that rtc, Hummingbird, and the practical type inference system all take strong steps forward in bringing the benefits of static typing to dynamic languages. Type Checking and Inference for Dynamic Languages by Brianna Ren Dissertation submitted to the Faculty of the Graduate School of the University of Maryland, College Park in partial fulfillment of the requirements for the degree of Doctor of Philosophy 2019 Advisory Committee: Professor Jeffrey S. Foster, Chair/Advisor Professor Michael Hicks Professor David Van Horn Professor Neil Spring Professor Donald Yeung c Copyright by Brianna Ren 2019 Acknowledgments I would like to first thank my advisor Jeff Foster for his guidance. I extend special thanks to all other members of my committee for providing me with valuable advice. I would also like to thank all members of PLUM, the Programming Languages group at the University of Maryland. I was fortunate enough to collaborate with Stevie Strickland, Milod Kazerounian, and talented undergrads John Toman and Alex Yu. ii Table of Contents Acknowledgements ii Table of Contents iii List of Tablesv List of Figures vi 1 Introduction1 1.1 Rtc: The Ruby Type Checker......................2 1.2 Just-in-Time Static Type Checking for Dynamic Languages......4 1.3 Practical Type Inference.........................6 2 The Dynamic Ruby Type Checker8 2.1 Using rtc..................................8 2.2 Implementation.............................. 19 2.3 Evaluation................................. 26 2.4 Related Work............................... 30 2.5 Conclusion................................. 32 3 Just-in-Time Static Type Checking for Dynamic Languages 33 3.1 Overview.................................. 33 3.2 Formalism................................. 40 3.3 Implementation.............................. 49 3.4 Experiments................................ 56 3.5 Related Work............................... 65 3.6 Conclusion................................. 70 4 Practical Type Inference 72 4.1 Introduction................................ 73 4.2 Motivating Examples........................... 75 4.2.1 Standard Type Inference Example................ 75 4.2.2 Practical Type Inference Examples............... 78 4.2.2.1 Structural Type to Actual Class Conversion..... 78 4.2.2.2 Reversed Solution Extraction............. 79 4.2.2.3 Method Name-based Inference............. 81 4.3 Formalism................................. 82 iii 4.3.1 Constraint Generation...................... 86 4.3.2 Standard Constraint Resolution................. 87 4.3.3 Standard Solution Extraction.................. 99 4.3.4 Practical Constraint Resolution................. 102 4.3.5 Practical Solution Extraction.................. 108 4.4 Implementation.............................. 109 4.5 Evaluation................................. 112 4.5.1 Overall Results.......................... 115 4.5.2 Importance of Key Practical Inference Features........ 129 4.5.3 Efficiency............................. 134 4.6 Related Work............................... 135 5 Conclusion and Future Directions 141 A Appendix 146 Bibliography 164 iv List of Tables 3.1 Talks Update Results........................... 65 4.1 Standard Constraint Resolution Rules.................. 88 4.2 Practical vs. standard inference results.................. 116 4.3 Practical Inference Features....................... 129 4.4 Type Inference Running Time...................... 134 v List of Figures 2.1 Basic usage of rtc.............................9 2.2 Illustration of proxy implementation................... 19 2.3 Illustration of proxy implementation - Sequence diagram for line 77. 20 2.4 Illustration of proxy implementation - Sequence diagram for line 79. 21 2.5 Summary of evaluation results...................... 27 3.1 Ruby on Rails Metaprogramming..................... 34 3.2 Methods Dynamically Created by User Code.............. 37 3.3 Type Signatures for Struct........................ 38 3.4 Source Language and Auxiliary Definitions............... 40 3.5 Type Checking System........................... 41 3.6 Dynamic Semantics............................ 44 3.7 Type checking results........................... 56 4.1 Basic Type Inference Usage....................... 73 4.2 Simple Ruby Method........................... 76 4.3 Reversed Solution Extraction...................... 79 4.4 Method name-based inference...................... 81 4.5 Source Language............................. 82 4.6 Possible and Implication Type Example................. 84 4.7 Constraint Generation.......................... 86 4.8 Standard Solution Extraction...................... 100 4.9 Merge to Union.............................. 101 4.10 Merge to Intersection........................... 102 4.11 Practical Constraint Resolution Rules.................. 103 4.12 Practical Solution Extraction...................... 110 4.13 CCT Methods............................... 118 4.14 Talks method............................... 132 vi Chapter 1: Introduction Object-oriented dynamic languages such as Ruby, Python, and JavaScript are popular, with many compelling features. Two of the main features are dynamic typing and metaprogramming. In dynamic typing, programmers do not need to declare types on variables, and variables are not associated with types until run-time. In addition, a variable's type compatibility is determined by the methods defined on it, as opposed to its actual class. Metaprogramming allows methods and classes to be added or modified at run-time. These powerful features help support rapid prototying and provide a high degree of flexibility and agility to the programmer. In static typing, type errors are caught early at compile time, which helps reduce the number of bugs and debugging time. In addition, the annotated
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages179 Page
-
File Size-