Resource Management and Tuples in C∀
Total Page:16
File Type:pdf, Size:1020Kb
Resource Management and Tuples in C8 by Robert Schluntz A thesis presented to the University of Waterloo in fulfillment of the thesis requirement for the degree of Master of Mathematics in Computer Science Waterloo, Ontario, Canada, 2017 © Robert Schluntz 2017 I hereby declare that I am the sole author of this thesis. This is a true copy of the thesis, including any required final revisions, as accepted by my examiners. I understand that my thesis may be made electronically available to the public. ii Abstract C8 is a modern, non-object-oriented extension of the C programming language. This thesis addresses several critical deficiencies of C, notably: resource management, a limited function- return mechanism, and unsafe variadic functions. To solve these problems, two fundamental language features are introduced: tuples and constructors/destructors. While these features exist in prior programming languages, the contribution of this work is engineering these features into a highly complex type system. C is an established language with a dedicated user-base. An important goal is to add new features in a way that naturally feels like C, to appeal to this core user-base, and due to huge amounts of legacy code, maintaining backwards compatibility is crucial. iii Acknowledgements I would like to thank my supervisor, Professor Peter Buhr, for all of his help, including reading the many drafts of this thesis and providing guidance throughout my degree. This work would not have been as enjoyable, nor would it have been as strong without Peter’s knowledge, help, and encouragement. I would like to thank my readers, Professors Gregor Richards and Patrick Lam for all of their helpful feedback. Thanks to Aaron Moss and Thierry Delisle for many helpful discussions, both work-related and not, and for all of the work they have put into the C8 project. This thesis would not have been the same without their efforts. I thank Glen Ditchfield and Richard Bilson, for all of their help with both the design and implementation of C8. I thank my partner, Erin Blackmere, for all of her love and support. Without her, I would not be who I am today. Thanks to my parents, Bob and Jackie Schluntz, for their love and support throughout my life, and for always encouraging me to be my best. Thanks to my best friends, Travis Bartlett, Abraham Dubrisingh, and Kevin Wu, whose companionship is always appreciated. The time we’ve spent together over the past 4 years has always kept me entertained. An extra shout-out to Kaleb Alway, Max Bardakov, Ten Bradley, and Ed Lee, with whom I’ve shared many a great meal; thank you for being my friend. Finally, I would like to acknowledge financial support in the form of a David R. Cheriton Graduate Scholarship and a corporate partnership with Huawei Ltd. iv Table of Contents List of Tables vii 1 Introduction1 1.1 C8 Background...................................1 1.1.1 C Background...............................1 1.1.2 Overloading.................................3 1.1.3 Polymorphism...............................8 1.1.4 Planned Features.............................. 10 1.2 Invariants...................................... 11 1.3 Resource Management............................... 12 1.4 Tuples........................................ 15 1.5 Variadic Functions................................. 18 1.6 Contributions.................................... 20 2 Constructors and Destructors 22 2.1 Design Criteria................................... 22 2.1.1 Calling Syntax............................... 26 2.1.2 Constructor Expressions.......................... 27 2.1.3 Function Generation............................ 28 2.1.4 Using Constructors and Destructors.................... 31 2.1.5 Implicit Destructors............................ 36 2.1.6 Implicit Copy Construction......................... 39 2.2 Implementation................................... 43 2.2.1 Array Initialization............................. 43 2.2.2 Global Initialization............................ 45 v 2.2.3 Static Local Variables........................... 46 2.2.4 Polymorphism............................... 48 2.3 Summary...................................... 49 3 Tuples 50 3.1 Multiple-Return-Value Functions.......................... 50 3.2 Tuple Expressions.................................. 53 3.2.1 Tuple Variables............................... 53 3.2.2 Tuple Indexing............................... 54 3.2.3 Flattening and Structuring......................... 54 3.3 Tuple Assignment.................................. 55 3.3.1 Tuple Construction............................. 57 3.4 Member-Access Tuple Expression......................... 58 3.5 Casting....................................... 60 3.6 Polymorphism.................................... 61 3.6.1 Assertion Inference............................. 63 3.7 Implementation................................... 63 4 Variadic Functions 69 4.1 Design Criteria................................... 69 4.1.1 Whole Tuple Matching........................... 70 4.1.2 A New Typeclass.............................. 71 4.2 Implementation................................... 74 5 Conclusions 81 5.1 Constructors and Destructors............................ 81 5.2 Tuples........................................ 81 5.3 Variadic Functions................................. 82 5.4 Future Work..................................... 82 5.4.1 Constructors and Destructors........................ 82 5.4.2 Tuples.................................... 87 5.4.3 Variadic Functions............................. 87 References 88 vi List of Tables 1.1 The different kinds of type parameters in C8 ....................9 vii Chapter 1 Introduction 1.1 C8 Background C81 is a modern non-object-oriented extension to the C programming language. As it is an extension of C, there is already a wealth of existing C code and principles that govern the design of the language. Among the goals set out in the original design of C8, four points stand out [3]. 1. The behaviour of standard C code must remain the same when translated by a C8 compiler as when translated by a C compiler. 2. Standard C code must be as fast and as small when translated by a C8 compiler as when translated by a C compiler. 3.C 8 code must be at least as portable as standard C code. 4. Extensions introduced by C8 must be translated in the most efficient way possible. Therefore, these design principles must be kept in mind throughout the design and development of new language features. In order to appeal to existing C programmers, great care must be taken to ensure that new features naturally feel like C. These goals ensure existing C code-bases can be converted to C8 incrementally with minimal effort, and C programmers can productively generate C8 code without training beyond the features being used. Unfortunately, C++is actively diverging from C, so incremental additions require significant effort and training, coupled with multiple legacy design-choices that cannot be updated. The current implementation of C8 is a source-to-source translator from C8 to GNU C [6]. The remainder of this section describes some of the important features that currently exist in C8, to give the reader the necessary context in which the new features presented in this thesis must dovetail. 1.1.1 C Background In the context of this work, the term object refers to a region of data storage in the execution environment, the contents of which can represent values [14, p. 6]. 1Pronounced “C-for-all”, and written C8 or Cforall. 1 One of the lesser-known features of standard C is designations. Designations are similar to named parameters in languages such as Python and Scala, except that they only apply to aggregate initializers. Note that in C8, designations use a colon separator, rather than an equals sign as in C, because this syntax is one of the few places that conflicts with the new language features. struct A{ int w,x,y,z; }; A a0={.x:4 .z:1, .x:8 }; A a1={1,.y:7, 6 }; A a2[4] = { [2]:a0, [0]:a1,{.z:3 } }; // equivalent to //A a0={ 0, 8, 0,1}; //A a1={ 1, 0, 7,6}; //A a2[4]={ a1,{ 0, 0, 0,3}, a0,{ 0, 0, 0,0}}; Designations allow specifying the field to initialize by name, rather than by position. Any field not explicitly initialized is initialized as if it had static storage duration [14, p. 141]. A designator specifies the current object for initialization, and as such any undesignated sub-objects pick up where the last initialization left off. For example, in the initialization of a1, the initializer of y is 7, and the unnamed initializer 6 initializes the next sub-object, z. Later initializers override earlier initializers, so a sub-object for which there is more than one initializer is only initialized by its last initializer. These semantics can be seen in the initialization of a0, where x is designated twice, and thus initialized to 8. C also provides compound literal expressions, which provide a first-class mechanism for creating unnamed objects. struct A{ int x,y; }; int f(A, int); int g( int *); f((A){ 3, 4 }, ( int){ 5 } = 10); g(( int[]){ 1, 2, 3 }); g(&( int){ 0 }); Compound literals create an unnamed object, and result in an lvalue, so it is legal to assign a value into a compound literal or to take its address [14, p. 86]. Syntactically, compound literals look like a cast operator followed by a brace-enclosed initializer, but semantically are different from a C cast, which only applies basic conversions and coercions and is never an lvalue. The C8 translator makes use of several GNU C extensions, including nested functions and