Cryptol version 2 Syntax

Layout

Groups of declarations are organized based on indentation. Declarations with the same indentation belong to the same group. Lines of text that are indented more than the beginning of a declaration belong to that declaration, while lines of text that are indented less terminate a group of declaration. Groups of declarations appear at the top level of a Cryptol file, and inside where blocks in expressions. For example, consider the following declaration group

This group has two declaration, one for f and one for g. All the lines between f and g that are indented more then f belong to f.

This example also illustrates how groups of declarations may be nested within each other. For example, the where expression in the definition of f starts another group of declarations, containing y and z. This group ends just before g, because g is indented less than y and z.

Cryptol supports block comments, which start with /* and end with */, and line comments, which start with // and terminate at the end of the line. Block comments may be nested arbitrarily.

Examples:

Identifiers

Cryptol identifiers consist of one or more characters. The first character must be either an English letter or underscore (_). The following characters may be an English letter, a decimal digit, underscore (_), or a prime ('). Some identifiers have special meaning in the language, so they may not be used in programmer-defined names (see Keywords).

Examples:

Keywords and Built-in Operators

The following identifiers have special meanings in Cryptol, and may not be used for programmer defined names:

The following table contains Cryptol’s operators and their associativity with lowest precedence operators first, and highest precedence last.

Operator precedences.
Operator Associativity
|| left
^ left
&& left
-> (types) right
!= == not associative
> < <= >= not associative
# right
>> << >>> <<< left
+ - left
* / % left
^^ right
! !! @ @@ left
(unary) - ~ right

Numeric Literals

Numeric literals may be written in binary, octal, decimal, or hexadecimal notation. The base of a literal is determined by its prefix: 0b for binary, 0o for octal, no special prefix for decimal, and 0x for hexadecimal.

Examples:

Numeric literals represent finite bit sequences (i.e., they have type [n]). Using binary, octal, and hexadecimal notation results in bit sequences of a fixed length, depending on the number of digits in the literal. Decimal literals are overloaded, and so the length of the sequence is inferred from context in which the literal is used.

Examples:

Bits

The type Bit has two inhabitants: True and False. These values may be combined using various logical operators, or constructed as results of comparisons.

Bit operations.
Operator Associativity Description
|| left Logical or
^ left Exclusive-or
&& left Logical and
!= == none Not equals, equals
> < <= >= none Comparisons
~ right Logical negation

If Then Else with Multiway

If then else has been extended to support multi-way conditionals.

Examples:

Tuples and Records

Tuples and records are used for packaging multiples values together. Tuples are enclosed in parenthesis, while records are enclosed in braces. The components of both tuples and records are separated by commas. The components of tuples are expressions, while the components of records are a label and a value separated by an equal sign.

Examples:

The components of tuples are identified by position, while the components of records are identified by their label, and so the ordering of record components is not important.

Examples:

The components of a record or a tuple may be accessed in two ways: via pattern matching or by using explicit component selectors. Explicit component selectors are written as follows:

Explicit record selectors may be used only if the program contains sufficient type information to determine the shape of the tuple or record. For example:

The components of a tuple or a record may also be access by using pattern matching. Patterns for tuples and records mirror the syntax for constructing values: tuple patterns use parenthesis, while record patterns use braces.

Examples:

Sequences

A sequence is a fixed-length collection of element of the same type. The type of a finite sequence of length n, with elements of type a is [n] a. Often, a finite sequence of bits, [n] Bit, is called a word. We may abbreviate the type [n] Bit as [n]. An infinite sequence with elements of type a has type [inf] a, and [inf] is an infinite stream of bits.

Note: the bounds in finite unbounded (those with ..) sequences are type expressions, while the bounds in bounded-finite and infinite sequences are value expressions.

Sequence operations.
Operator Description
# Sequence concatenation
>> << Shift (right,left)
>>> <<< Rotate (right,left)
@ ! Access elements (front,back)
@@ !! Access sub-sequence (front,back)

There are also lifted point-wise operations.

Explicit Type Instantiation

If f is a polymorphic value with type:

Demoting Numeric Types to Values

The value corresponding to a numeric type may be accessed using the following notation:

Here t should be a type expression with numeric kind. The resulting expression is a finite word, which is sufficiently large to accomodate the value of the type:

Explicit Type Annotations

Explicit type annotations may be added on expressions, patterns, and in argument definitions.

May 4, 2014