220 likes | 324 Views
Extending Type Systems in a Library. Yuriy Solodkyy Jaakko Järvi Esam Mlaih. Motivation. Type systems are good for you! make sure certain bugs never appear better optimizations Type systems of a general purpose programming language are typically not extensible a fixed part of a compiler
E N D
Extending Type Systems in a Library Yuriy Solodkyy Jaakko Järvi Esam Mlaih
Motivation • Type systems are good for you! • make sure certain bugs never appear • better optimizations • Type systems of a general purpose programming language are typically not extensible • a fixed part of a compiler • There are many domain specific type systems Texas A&M University
Use cases • Physical quantities • Types to track some semantic properties: • nullability, sign, oddity of a number • security vulnerability to format strings • usage of user pointers in kernel space • deadlocks and data races • Regular Expression Types Texas A&M University
Goal • Explore how far a pure library solution suffices to extending a type system Texas A&M University
Contributions • We report on implementing simple type qualifiers as a C++ library • We implement regular expression types (in a limited form) to check XML data • We provide a framework to help others in extending the C++ type system for their abstractions Texas A&M University
Example returns only positive numbers // a is a positive value double a = current_height(); // b is a positive value double b = max_allowed_height(); // b-a may be negative though! Result is always positive double c = std::sqrt(b-a); // b+a is assumed to be positive. Unless there is bug! double d = std::sqrt(b+a); upper bound for values from previous call difference is positive, but not for type system argument and result are always positive Texas A&M University
What do we need? • Typing rules • Evaluation rules • Subtyping rules Texas A&M University
How do we achieve that in C++? • Typing rules • Type construction via class templates • Evaluation rules • Function templates and overloading • Subtyping rules • A dedicated meta-function Texas A&M University
Useful building blocks • Typing rules • tuple, variant, optional • Evaluation rules • enable_if • Subtyping rules • MPL • Interoperability of the above libraries! Texas A&M University
Type qualifiers • Allow tracking of semantic properties like: • immutability of a certain value (const) • sign of a number (pos, neg) • assumptions about pointers (optional, nonnull) • trustworthiness of a certain value (tainted, untainted) • oddity of a number (odd, even) • origin of a pointer (user, kernel) Texas A&M University
Example: Qualifiers’ Hello World Declare few qualifiers: Q is positive if T <: Q T Q is negative if Q T <: T Define how different operations transfer properties #include <xtl/qualdecl.hpp> DECLARE_NEGATIVE_QUALIFIER(pos); DECLARE_POSITIVE_QUALIFIER(tainted); // ... Other qualifiers ... namespace xtl { template <> struct minus<pos, neg> { typedef qual<pos> type; }; template <> struct minus<neg, pos> { typedef qual<neg> type; }; template <> struct mul<pos, pos> { typedef qual<pos> type; }; template <> struct mul<pos, neg> { typedef qual<neg> type; }; template <> struct mul<nonnull, nonnull>{ typedef qual<nonnull> type;}; template <> struct div<nonnull, nonnull>{ typedef qual<nonnull> type;}; } // of namespace xtl int main() { untainted<nonnull<neg<int> > >a(-42); pos<untainted<nonnull<int> > >b(7); neg<nonnull<long> >c = a * b; // OK: drop negative qualifier untainted //nonnull<pos<double> > d = b - a; // Error: nonnull isn’t carried by - pos<tainted<double> >e = b + a*c; // OK to add positive qualifier //pos<double> f = e; // Error: ... but not OK to drop it! } Subtraction does not carry nonnull Positive qualifiers can be added to result type... Multiplication carries nonnull & negativeness on pos & neg arguments Declare your variables with appropriate properties ... but not dropped once they are there! Texas A&M University
Example function descend accepts only positive numbers we achieve this by restricting its argument type to be a subtype of pos<double> we convert value of a subtype into a value of a supertype // Example definition that accepts only positive doubles template<class U> typename enable_if< typename is_subtype<U, pos<double> >::type, void >::type descend(const U& altitude) { pos<double>a = subtype_cast<pos<double> >(altitude); //... }; // Data coming from measurements is marked untainted extern pos<untainted<int> >get_corridor_height(); untainted<pos<int> >a = get_corridor_height(); descend(a); // no negative altitudes here! returns a value that is both: positive and untainted a can hold positive, untainted values. order of qualifiers is not important! no negative altitudes can appear here! Texas A&M University
Qualifiers summary • Easy to define and use • Cannot handle flow-sensitive qualifiers • Cannot handle arbitrary reference qualifiers (e.g. aliasing related) Texas A&M University
Type system for XML • Types can describe XML elements with certain structure • Subtyping describes structurally more powerful types • Compile-time assurance that only valid XML documents are produced • Value-preserving type conversions Texas A&M University
typedef element<name, string> XMLname; typedef element<email,string> XMLemail; typedef element<icq, int>XMLicq; typedef element<contact, boost::variant< XMLemail, XMLicq > > XMLcontact; typedef element<person, fusion::tuple< XMLname, XMLcontact > > XMLperson; <xsd:elementname="name"type="xsd:string"/> <xsd:elementname="email"type="xsd:string"/> <xsd:elementname="icq"type="xsd:decimal"/> <xsd:elementname="contact"> <xsd:complexType> <xsd:choice> <xsd:elementref="email"/> <xsd:elementref="icq"/> </xsd:choice> </xsd:complexType> </xsd:element> <xsd:elementname="person"> <xsd:complexType> <xsd:sequence> <xsd:elementref="name"/> <xsd:elementref="contact"/> </xsd:sequence> </xsd:complexType> </xsd:element> Example we use a dedicated type element to represent XML elements we use a dedicated type element to represent XML elements for each tag we create a dedicated tag-type for each tag we create a dedicated tag-type we map XML data types into C++ types we map XML data types into C++ types back references are mapped to previous typedefs back references are mapped to previous typedefs back references are mapped to previous typedefs XML Schema’s choice is mapped to Boost variant XML Schema’s choice is mapped to Boost variant XML Schema C++ XML Schema’s sequence is mapped to Fusion’s tuple XML Schema’s sequence is mapped to Fusion’s tuple Texas A&M University
Tel <: AnyContact ICQ <: AnyContact Name, Tel, ICQ <: Name, AnyContact, AnyContact Person <: PersonEx Example Instantiate an XML snippet that corresponds to Person type // ... typedef variant<Email,Tel,ICQ> AnyContact; typedef element<person, tuple<Name, Tel, ICQ> > Person; typedef element<person, tuple<Name, AnyContact, AnyContact> > PersonEx; int main() { Person p(make_tuple(Name("Yuriy"),Tel("555-4321"),ICQ(1234))); PersonEx x = p; // OK: Subtyping conversion // p = x; // ERROR: Not in subtyping relation ifstream xml("old-person.xml"); xml >> x; // read data from XML file. assumes file exist cout << x << endl; // show XML source on the screen } Person <: PersonEx Assignment involves subtype conversion PersonEx is not a subtype of Person Parses only XML files that correspond to PersonEx schema Produces XML source on the screen Texas A&M University
XDuce • Type • set of sequences over a certain domain • Regular Expression Types • concatenation : A,B • alternation : A|B • repetition : A* • optional : A? • type construction : l[A] • recursion : X = A,X | ø • Subtyping • inclusion between the sets defined by types Texas A&M University
C++ • Type • set of sequences over a certain domain • Regular Expression Types • concatenation : A,B tuple<A,B> • alternation : A|B variant<A,B> • repetition : A* vector<A> • optional : A? optional<A> • type construction: l[A] element<l,A> • recursion : X = A,X | ø– • Subtyping • is_subtype and subtype_cast Texas A&M University
XTL – eXtensible Typing Library • Provides a common interface for defining custom subtyping relation • Provides a common interface for defining conversion from a subtype to a supertype • Provides some ready definitions that can be used in defining other type systems: • subtyping of array types • subtyping of function types • subtyping of sequences and union types • subtyping of qualified types Texas A&M University
Limitations • Reflexivity of subtyping relation has to be stated manually for each new type. • No implicit transitivity of subtyping relation. • Meta-function join may return an arbitrary upper bound. Texas A&M University
Future work • Look at applying our approach to ownership types • Look at alternative representations of type qualifiers • Extend subtyping of repetitions • Create a library of useful type qualifiers Texas A&M University
Thank You! Questions? Texas A&M University