struct<\/code>)<\/li><\/ul>\n\n\n\nEnumeration and tagged union types serve a similar purpose: to discriminate different cases. Tagged unions further allow for data to be stored per variant, whereas enumeration types do not store data. Enumerations are used for named constants.<\/p>\n\n\n\n
For example, consider an enumeration of DNS record types (we list only here a few variants):<\/p>\n\n\n\n
enum<\/strong> DNSRecordType { A, NS, CNAME, SOA, MX, TXT }<\/code><\/pre>\n\n\n\nThen one can access each constant as DNSRecordType::A<\/code>, DNSRecordType::NS<\/code>, et cetera.<\/p>\n\n\n\nA classic examples of disjoint union types are to implement so-called option types. For example, in places where some variant of the enumeration above is expected or no value can be given, one may use the following data type:<\/p>\n\n\n\n
union<\/strong> OptionalDNSRecordType { None, Some(DNSRecordType) }<\/code><\/pre>\n\n\n\nTo construct an element of a tagged union type, one uses the constructor for each variant. In the case of no-argument variants, this is similar in use as constants in enumerations. For variants that accept parameters, these have to be supplied to the variant constructor. For example, OptionalDNSRecordType::Some(DNSRecordType::A)<\/code> is an element of OptionalDNSRecordType<\/code>.<\/p>\n\n\n\nTo be able to test what variant is used, we introduce the “if let” statement. This statement tests the variant of a union type and at the same time performs a pattern match to extract data from the matched variant.<\/p>\n\n\n\n
auto<\/strong> x = OptionalDNSRecordType::Some(DNSRecordType::A);\n\nif<\/strong> (let<\/strong> OptionalDNSRecordType::Some(y) = x) {\n \/\/ y is bound to DNSRecordType::A here\n if<\/strong> (let<\/strong> y = DNSRecordType::A) {\n assert true<\/strong>;\n } else<\/strong> {\n assert false<\/strong>;\n }\n}<\/code><\/pre>\n\n\n\nProduct types can be used for modeling structured data, such as packet headers. Each field has an associated type, thus constraining what elements can be stored in the type. Product types are also known as records. For example, here is a structure modeling the UDP packet header:<\/p>\n\n\n\n
struct<\/strong> UDPHeader {\n u16<\/strong> source_port,\n u16<\/strong> dest_port,\n u16<\/strong> length,\n u16<\/strong> checksum\n}<\/code><\/pre>\n\n\n\nElements of product types can be constructed by a constructor literal, that takes an element for each of the fields that are part of the product. For example, UDPHeader{ source_port: 82, dest_port: 1854, length: 0, checksum: 0 }<\/code> constructs an element of the type defined above.<\/p>\n\n\n\nFurther, user-defined types may be recursive<\/em>, and thus allow modeling interesting structures such as binary trees. Consequently, one can define recursive functions that traverse such structures. See for example:<\/p>\n\n\n\nunion<\/strong> Tree {\n Leaf(u8<\/strong>),\n Node(Tree,u8<\/strong>,Tree)\n}\nfunc<\/strong> mirror(Tree t) -> Tree {\n if<\/strong> (let<\/strong> Tree::Leaf(u) = t) {\n return<\/strong> t;\n }\n if<\/strong> (let<\/strong> Tree::Node(l, n, r) = t) {\n return<\/strong> Tree::Node(mirror(r), n, mirror(l));\n }\n return<\/strong> Leaf(0); \/\/ not reachable\n}<\/code><\/pre>\n\n\n\nType Checking and Inference<\/h2>\n\n\n\n
The type checker ensures that protocols written in PDL are type safe: it is ensured statically that no element of one type is assigned to another type. It is still possible to transform elements from one type to another, either by the means of casting<\/em> or by calling a function.<\/p>\n\n\n\nThe type checker in Reowolf futhermore elaborates protocols in which not sufficient typing information is supplied. This is called type inference<\/em>. This reduces the need for protocol programmers to supply typing information, if such information can be deduced automatically from the surrounding context.<\/p>\n\n\n\nThe type checker and inference system works in tandem with user-defined algebraic data types. Also, in pattern matching constructs such as the “if let” statement, the types of the variables occurring in patterns are automatically inferred.<\/p>\n\n\n\n
Consider the following function, that computes the size of a binary tree. It declares an automatic variable (s<\/code>) that contains the result of the function. Further, it automatically infers the type of the pattern variables (l<\/code>, n<\/code>, r<\/code>) that follows from the definition of the Node<\/code> variant in the Tree<\/code> data type.<\/p>\n\n\n\nfunc<\/strong> size(Tree t) -> u32<\/strong> {\n auto<\/strong> s = 0;\n if<\/strong> (let<\/strong> Tree::Node(l, n, r) = t) {\n s += 1;\n s += size(l) + size(r);\n } else<\/strong> {\n s = 1;\n }\n return<\/strong> s;\n}<\/code><\/pre>\n\n\n\nWe shall now consider a number of negative examples. One assigns two different variables (val16<\/code> and val32<\/code>), and then leaves unspecified the type of the third variable (a<\/code>) by the use of the auto<\/strong> keyword.<\/p>\n\n\n\nfunc<\/strong> error1() -> u32<\/strong> {\n u16<\/strong> val16 = 123;\n u32<\/strong> val32 = 456;\n auto<\/strong> a = val16;\n a = val32;\n return<\/strong> 0;\n}<\/code><\/pre>\n\n\n\nIn this case, an error is triggered, because there exists no type to which both 16-bit unsigned integers and 32-bit unsigned integers can be assigned. The same kind of error occurs whenever one performs an operation on two different types. Reowolf has no<\/em> automatic implicit casting. This type strictness is added to ensure that code is never ambiguous. However, casting operators<\/em> are used to explicitly mark where casting happens in the code.<\/p>\n\n\n\nfunc<\/strong> error2() -> s32<\/strong> {\n s8<\/strong> b = 0b00;\n s64<\/strong> l = 1234;\n auto<\/strong> r = b + l;\n return<\/strong> 0;\n}\nfunc<\/strong> good1() -> s32<\/strong> {\n s8<\/strong> b = 0b00;\n s64<\/strong> l = 1234;\n auto<\/strong> r = cast<\/strong><s64>(b) + l;\n return<\/strong> r;\n}\nfunc<\/strong> good2() -> s32<\/strong> {\n s8<\/strong> b = 0b00;\n s64<\/strong> l = 1234;\n auto<\/strong> r = cast<\/strong>(b) + l; \/\/ type inferencer can make the jump\n return<\/strong> r;\n}<\/code><\/pre>\n\n\n\nGeneric Types and Functions<\/h2>\n\n\n\n
Reowolf now supports generic type parameters, that can be used both in user-defined data type definitions and in function definitions. Generic type parameters are also used by the type checker and type inferencer. For example, it is possible to define the generic option type:<\/p>\n\n\n\n
union<\/strong> Option<T> { None, Some(T) }<\/code><\/pre>\n\n\n\nThe generic type can be instantiated by a concrete type, including the primitive types such as integers. It is also possible to define generic functions, for example:<\/p>\n\n\n\n
func<\/strong> some<T>(Option<T> s) -> T {\n if<\/strong> (let<\/strong> Option::Some(c) = s) { return<\/strong> c; }\n while<\/strong> (true<\/strong>) {} \/\/ does not terminate for Option::None\n}<\/code><\/pre>\n\n\n\nFurthermore, generic types are also added to input and output ports: this allows protocol programmers to specify precisely what value is expected during communication. For example, the sync channel<\/em> is defined as:<\/p>\n\n\n\nprimitive<\/strong> sync<T>(in<\/strong><T> i, out<\/strong><T> o) {\n while<\/strong> (true<\/strong>) {\n sync<\/strong> {\n if<\/strong> (fires<\/span>(i) && fires<\/span>(o)) {\n auto<\/strong> m = get<\/span>(i);\n put<\/span>(o, m);\n} } } }<\/code><\/pre>\n\n\n\nThe sync channel can then be instantiated by different concrete types: e.g. sync<u8><\/code> is a byte channel, and sync<u8[]><\/code> is a byte array channel. The additional type information is useful to avoid communicating with incompatible message types.<\/p>\n\n\n\nUsability Improvements<\/h2>\n\n\n\n
The module and namespace system is improved. Protocol descriptions live in their own namespace (each domain name is a separate namespace) to prevent naming conflicts of definitions among multiple protocol authors. Importing symbols from other modules is allowed, and checks for naming conflicts among symbols imported from other modules and locally defined symbols.<\/p>\n\n\n\n
An important aspect of this release is to have user-friendly error messages. This helps the protocol programmer to identify the error in the protocol description, that can be quickly resolved. For example:<\/p>\n\n\n\n
struct<\/strong> Pair<T1, T2>{ T1 first, T2 second }\nfunc<\/strong> bar(s32<\/strong> arg1, s8<\/strong> arg2) -> s32<\/strong> {\n auto<\/strong> shoo = Pair<s32, s8>{ first: arg1, seond: arg2 };\n return<\/strong> arg1;\n}<\/code><\/pre>\n\n\n\nproduces the following user-friendly error message:<\/p>\n\n\n\n
ERROR: This field does not exist on the struct 'Pair'\n +- at 3:45\n | \n | auto shoo = Pair<s32, s8>{ first: arg1, seond: arg2 };\n | ~~~~~\n<\/code><\/pre>\n\n\n\nRoadmap<\/h2>\n\n\n\n
After this release we can continue our work in the following directions:<\/p>\n\n\n\n
- The semantics of Reowolf’s sync<\/strong> block has to be adapted to make it possible to be driven by an efficient distributed consensus algorithm. For this, we introduced so-called scoped<\/em> sync statements, that allows for a run-time discovery of neighboring components.<\/li>
- Modelling existing transport layer protocols, such as TCP and UDP, as Reowolf protocols. This allows us to convincingly demonstrate the expressiveness of the protocol description language, and to compare our implementation’s efficiency with existing networking stacks. These transport layer implementations would make use of native IP components. Further ahead, we can model existing Internet protocols such as ICMP, DNS, HTTP, ….<\/li>
- Make first approaches to integrating Reowolf into the operating system kernel. We are exploring which operating system is most suitable for integration. Considering that our user-mode implementation is written in Rust, we are seeking whether our kernel implementation can also be written (mostly) in Rust.<\/li>
- Work on the specification of the Protocol Description Language (PDL), leading to a standardization track. Part of this specification work is the need to formalize<\/em>, in an unambiguous manner, the semantics of protocols specified in PDL. Formalized semantics increases the future potential for formal verification of protocols, and allows us to define the correctness criteria of Reowolf implementations.<\/li><\/ul>\n\n\n\n
We will keep you updated!<\/p>\n\n\n\n
The Reowolf Team
– June 4, 2021<\/p>\n","protected":false},"excerpt":{"rendered":"
We are happy to release this milestone of the Reowolf project: Reowolf version 1.1. This is an alpha release. The milestone improves the structural aspects of Protocol Description Language (PDL), which increases the declarative aspects of protocol descriptions needed for modeling Internet protocols (e.g. TCP, UDP, ICMP, DNS). This post summarizes the improvements, and further […]<\/p>\n","protected":false},"author":1,"featured_media":9126,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38],"tags":[35],"class_list":["post-9110","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-releases","tag-release"],"_links":{"self":[{"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/posts\/9110","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/comments?post=9110"}],"version-history":[{"count":12,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/posts\/9110\/revisions"}],"predecessor-version":[{"id":9134,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/posts\/9110\/revisions\/9134"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/media\/9126"}],"wp:attachment":[{"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/media?parent=9110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/categories?post=9110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/reowolf.net\/wp-json\/wp\/v2\/tags?post=9110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}