mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-12-03 18:22:58 +03:00
3393 lines
131 KiB
TeX
3393 lines
131 KiB
TeX
\commentout{
|
|
\begin{code}
|
|
module CrashCourse where
|
|
\end{code}
|
|
}
|
|
|
|
%#####################################################################
|
|
\chapter{A Crash Course in Cryptol}
|
|
\label{cha:crash-course-cryptol}
|
|
|
|
Before we can delve into cryptography, we have to get familiar with
|
|
Cryptol. This chapter provides an introduction to Cryptol, just to
|
|
get you started. The exposition is not meant to be comprehensive, but
|
|
rather as an overview to give you a feel of the most important tools
|
|
available. If a particular topic appears hard to approach, feel free
|
|
to skim it over for future reference.
|
|
|
|
A full language reference is beyond the scope of this document at this
|
|
time.
|
|
% The language features not covered in this document at this time
|
|
% include:
|
|
% \begin{itemize}
|
|
% \item feature one
|
|
% \item feature two
|
|
% \end{itemize}
|
|
% \todo[inline]{2.1: Add list here of language features not yet
|
|
% covered.}
|
|
|
|
% TODO The full grammar for Cryptol is included
|
|
% in~\autoref{cha:cryptol-grammar}.
|
|
|
|
%=====================================================================
|
|
\section{Basic data types}
|
|
\label{sec:basic-data-types}
|
|
|
|
Cryptol provides seven basic data types: bits, sequences, integers,
|
|
integers-modulo-n, rationals, tuples, and records.
|
|
Words (i.e., $n$-bit numbers) are a special case
|
|
of sequences. Note that, aside from the base types (like bits and integers),
|
|
Cryptol types can be nested as deep as you like. That is, we can have
|
|
records of sequences containing tuples made up of other records, etc.,
|
|
giving us a rich type-system for precisely describing the shapes of
|
|
data our programs manipulate.
|
|
|
|
While Cryptol is statically typed, it uses type inference to supply
|
|
unspecified types. That is, the user usually does {\em not} have to
|
|
write the types of all expressions; they will be automatically inferred by the
|
|
type-inference engine. Of course, in certain contexts the user might
|
|
choose to supply a type explicitly. The notation is simple: we simply
|
|
put the expression, followed by {\tt :} and the type. For instance,
|
|
\begin{Verbatim}
|
|
12 : [8]
|
|
\end{Verbatim}
|
|
means the value {\tt 12} has type {\tt [8]}, i.e., it is an 8-bit
|
|
word. We can also supply partial types. For example,
|
|
\begin{Verbatim}
|
|
12 : [_]
|
|
\end{Verbatim}
|
|
means that \texttt{12} has a word type with an unspecified number of
|
|
bits. Cryptol will infer the unspecified part of the type in this
|
|
case. We shall see many other examples of typed expressions in the
|
|
following discussion.
|
|
|
|
%=====================================================================
|
|
\sectionWithAnswers{Bits: Booleans}{sec:bits}
|
|
|
|
The type {\tt Bit}\indTheBitType represents a single bit of
|
|
information. There are precisely two values of this type: {\tt
|
|
True}\indTrue and {\tt False}\indFalse. Bit values play an important
|
|
role in Cryptol, as we shall see in detail shortly. In particular, the
|
|
test expression in an {\tt if-then-else} statement must have the type
|
|
{\tt Bit}. The logical operators {\tt \&\&}\indAnd (and), {\tt
|
|
||}\indOr (or), {\tt \Verb|^|}\indXOr (xor), and {\tt
|
|
\Verb|~|}\indComplement (complement) provide the basic operators
|
|
that act on bit values.
|
|
|
|
\begin{Exercise}\label{ex:dataBit}
|
|
Type in the following expressions at the Cryptol prompt, and observe
|
|
the output:
|
|
\begin{Verbatim}
|
|
True
|
|
false
|
|
False : Bit
|
|
if True && False then 0x3 else 0x4
|
|
False || True
|
|
(True && False) ^ True
|
|
~False
|
|
~(False || True)
|
|
\end{Verbatim}
|
|
Remember that Cryptol is case sensitive, and hence {\tt false} is
|
|
different from {\tt False}.\indCaseSensitive
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:dataBit}
|
|
Here is the response from Cryptol, in order:
|
|
\begin{small}
|
|
\begin{Verbatim}
|
|
True
|
|
[error] at <interactive>:1:1--1:6 Value not in scope: false
|
|
False
|
|
0x4
|
|
True
|
|
True
|
|
True
|
|
False
|
|
\end{Verbatim}
|
|
\end{small}
|
|
\end{Answer}
|
|
|
|
\begin{tip}
|
|
Cryptol provides extensive command line/tab completion; use
|
|
up/down-arrow to see your previous commands, hit tab to complete
|
|
identifier names, etc.
|
|
\end{tip}
|
|
|
|
%=====================================================================
|
|
\sectionWithAnswers{Words: Numbers}{sec:words}
|
|
|
|
A word is simply a numeric value with some number of bits,
|
|
corresponding to the usual notion of binary numbers.\indTheWordType To
|
|
match our observation of how cryptographers use binary numbers,
|
|
Cryptol defaults to interpreting words as non-negative ($\geq 0$)
|
|
values (i.e., no negative numbers). However, words
|
|
can be arbitrarily large: There is no predefined maximum number of
|
|
bits that we are limited to.\indArbitraryPrecision The type of $n$-bit
|
|
words is written \texttt{[n]}; e.g. \texttt{[8]} is the 8-bit word type.
|
|
|
|
By default, Cryptol prints words in base 16. You might find it useful
|
|
to set the output base to be 10 while working on the following
|
|
example. To do so, use the command:\indSettingBase
|
|
\begin{Verbatim}
|
|
:set base=10
|
|
\end{Verbatim}
|
|
The supported values for this setting are 2 (binary), 8 (octal), 10
|
|
(decimal), and 16 (hexadecimal). Conversely, we can \emph{write}
|
|
numbers in these bases in Cryptol programs too:
|
|
\begin{Verbatim}
|
|
0b11111011110 // binary
|
|
0o3736 // octal
|
|
2014 // decimal
|
|
0x7de // hexadecimal
|
|
\end{Verbatim}
|
|
|
|
Decimal numbers pose a problem in a bit-precise language like Cryptol.
|
|
Numbers represented in a base that is a power of two unambiguously
|
|
specify the number of bits required to store each digit. For example
|
|
\texttt{0b101} takes three bits to store, so its type is \texttt{[3]}.
|
|
A hexadecimal digit takes 4 bits to store, so \texttt{0xabc} needs 12
|
|
bits, and its type is \texttt{[12]}. On the other hand, a decimal
|
|
digit could require anywhere from 1 to 4 bits to represent, so the
|
|
number of digits does not determine the type. Decimal numbers may
|
|
assume any of a variety of types in Cryptol; that is, they are
|
|
\emph{polymorphic}.\indPolymorphism For example, \texttt{19} could
|
|
have the unbounded type \texttt{Integer} (see~\autoref{sec:integer}),
|
|
type \texttt{[8]}, type \texttt{[5]}, or any other word type with at
|
|
least 5 bits.
|
|
|
|
\paragraph*{Defaulting and explicit types}\indDefaulting
|
|
Polymorphic values in a Cryptol program are subject to
|
|
\emph{defaulting}, meaning that Cryptol will choose specific types to
|
|
represent them. Cryptol usually prints a message whenever defaulting
|
|
occurs, showing which type was chosen. For numbers, Cryptol usually
|
|
chooses either \texttt{Integer} or the word type with the
|
|
\emph{smallest} number of bits required to represent them. Users can
|
|
override this by giving an explicit type signature.\indSignature
|
|
|
|
\todo[inline]{2.1: Make decision about
|
|
\href{https://www.galois.com/cryptol/ticket/217}{ticket \#217} for
|
|
the suppression of bitwidth assumption messages.}
|
|
%% If you get tired of these messages, you can suppress them with the
|
|
%% \texttt{:set reportAssuming=off} command. Alternatively, you can
|
|
%% help Cryptol avoid from having to assume anything by using binary,
|
|
%% octal, or hexadecimal constants exclusively. Many cryptographic
|
|
%% algorithms use decimal for their constants, but it is important to
|
|
%% keep track of how many bits they need, so the current behavior was
|
|
%% deemed a good compromise.
|
|
|
|
\begin{Exercise}\label{ex:decimalType}
|
|
Try writing some decimal numbers at different types, like
|
|
\texttt{12:[4]} and \texttt{50:[8]}. How does Cryptol respond if
|
|
you write \texttt{19:[4]}, and why? What is the largest decimal
|
|
number you can write at type \texttt{[8]}? What is the smallest
|
|
allowable bit size for \texttt{32}? What is the smallest allowable
|
|
bit size for \texttt{0}?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:decimalType}
|
|
Cryptol prints the error ``\texttt{Unsolvable constraint: 4 >= 5}'',
|
|
because \texttt{19} requires at least 5 bits to represent.
|
|
\texttt{255:[8]} is the largest value of type \texttt{[8]}.
|
|
\texttt{[6]} is the smallest type for \texttt{32}. \texttt{[0]} is
|
|
the smallest type for \texttt{0}.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:setBase}
|
|
Experiment with different output bases by issuing {\tt :set
|
|
base=10}, and other base values. Also try writing numbers directly
|
|
in different bases at the command line, such as {\tt 0o1237}. Feel
|
|
free to try other bases. What is the hexadecimal version of the
|
|
octal number {\tt 0o7756677263570015}?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:setBase}
|
|
{\tt 0xfeedfacef00d}.
|
|
\end{Answer}
|
|
|
|
\note{We will revisit the notion of words in \autoref{sec:words2},
|
|
after we learn about sequences.}
|
|
|
|
%=====================================================================
|
|
\sectionWithAnswers{Integers: Unbounded numbers}{sec:integer}
|
|
|
|
The type \texttt{Integer}\indTheIntegerType represents mathematical
|
|
integers of unlimited size. To write an integer value in Cryptol,
|
|
simply write the number in decimal, optionally annotated with
|
|
\texttt{:Integer} to disambiguate the type. Numbers written in base 2,
|
|
8, or 16 are always $n$-bit words, and never have type
|
|
\texttt{Integer}. However, they can be converted to unbounded integers
|
|
using \texttt{toInteger}. For example, \texttt{toInteger 0xff}
|
|
represents the integer 255. To write a negative integer, simply negate
|
|
the result: For example, \texttt{-12} and \texttt{- toInteger 0xc}
|
|
represent the integer $-12$.
|
|
|
|
\begin{Exercise}\label{ex:int:1}
|
|
Compare the results of evaluating the expressions \texttt{0x8 + 0x9}
|
|
and \texttt{toInteger 0x8 + toInteger 0x9}. Also try evaluating
|
|
\texttt{toInteger (- 0x5)}. Can you explain the results?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:int:1}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
0x1
|
|
17
|
|
11
|
|
\end{Verbatim}
|
|
\texttt{0x8 + 0x9} evaluates to \texttt{0x1} because addition on 4-bit
|
|
words wraps around when the sum is 16 or more and it overflows. On the
|
|
other hand, \texttt{Integer} addition never overflows, so the answer
|
|
is 17. The final result is also due to wraparound: \texttt{- 0x5}
|
|
evaluates to \texttt{0xb} or 11, which is $-5 + 16$.
|
|
\end{Answer}
|
|
|
|
In addition to the unbounded \texttt{Integer} type, there are also a
|
|
collection of bounded integer types: \texttt{Z n} for each finite
|
|
positive \texttt{n}. \texttt{Z n} represents the ring of integers modulo \texttt{n}.
|
|
Just like with fixed-width bitvector values, arithmetic in
|
|
\texttt{Z n} will ``wrap around'' (i.e., be reduced modulo \texttt{n})
|
|
when values get too large.
|
|
\begin{Exercise}\label{ex:int:2}
|
|
Compare the results of evaluating \texttt{ (5 : Z 7) + (6 : Z 7) }
|
|
with \texttt{ toInteger (5 : Z 7) + toInteger (6 : Z 7) }.
|
|
What is the result of \texttt{ -3 : Z 7 }?
|
|
Were the results what you expected?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:int:2}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
4
|
|
11
|
|
4
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
\section{Rationals}
|
|
\label{sec:rational}
|
|
|
|
The type \texttt{Rational}\indTheRationalType represents the rational number subset
|
|
of the real line: that is, those numbers that can be represented
|
|
as a ratio of integers. You can explicitly create rational values using
|
|
the \texttt{ratio} function, which accepts the numerator and denominator
|
|
as integer values, or you can create a rational value from an
|
|
integer using the \texttt{fromInteger} function. Rational values can
|
|
also be created directly from literals the same way as for
|
|
\texttt{Integer}.
|
|
|
|
For example, all of the following expression create the same
|
|
value representing one half:
|
|
\begin{Verbatim}
|
|
ratio 1 2
|
|
ratio 2 4
|
|
(1 /. 2) : Rational
|
|
(recip 2) : Rational
|
|
(fromInteger (-1) /. fromInteger (-2)) : Rational
|
|
\end{Verbatim}
|
|
|
|
Note, the division operation on \texttt{Rational} is
|
|
written \texttt{/.}, and should not be confused with
|
|
\texttt{/}, which is the division operation for words
|
|
and integers.
|
|
|
|
|
|
%===============================================================================
|
|
\section{Floating Point Numbers}
|
|
\label{sec:floats}
|
|
|
|
The family of types \texttt{Float e p}\indTheFloatType represent IEEE 754
|
|
floating point numbers with \texttt{e} bits in the exponent and
|
|
\texttt{p-1} bits in the mantissa. The family is defined in a built-in
|
|
module called \texttt{Float} so to use it you'd need to either import
|
|
it in you Cryptol specification or use \texttt{:m Float} on the
|
|
Cryptol REPL.
|
|
|
|
Floating point numbers may be written using either integral or fractioanl
|
|
literals. In general, literals that cannot be represented exactly are
|
|
rejected with a type error, with the exception of decimal fractional litrals
|
|
which are rounded to the nearest even representable numbers.
|
|
|
|
Floating point numbers may be manipulated and compared using
|
|
standard Cryptol operators, such as \texttt{+}, \texttt{==}, and \texttt{/.}
|
|
(but {\em not} \texttt{/} which is only for integral types).
|
|
When using the standard Cryptol operators the results that cannot be
|
|
represented exactly are rounded to the nearest even representable number.
|
|
|
|
The module \texttt{Float} provides additional functionality specific
|
|
to floating point numbers. In particular, it contains constants for
|
|
writing special floating point values, and arithmetic operations
|
|
that are parameterized on the rounding mode to use during computation
|
|
(e.g., \texttt{fpAdd}).
|
|
|
|
Of particular importance is the relation \texttt{=.=} for comparing
|
|
floating point numbers semantically, rather that using the IEEE equality,
|
|
which is done by \texttt{==}. The behavior of the two differs
|
|
mostly on special values, here are some examples:
|
|
\begin{Verbatim}
|
|
Float> fpNaN == (fpNaN : Float64)
|
|
False
|
|
Float> fpNaN =.= (fpNaN : Float64)
|
|
True
|
|
Float> 0 == (-0 : Float64)
|
|
True
|
|
Float> 0 =.= (-0 : Float64)
|
|
False
|
|
\end{Verbatim}
|
|
|
|
Cryptol supports reasoning about floating point numbers using the
|
|
{\texttt What4} interface to solvers that support IEEE floats.
|
|
These back-ends have names starting with {\texttt w4}, for example,
|
|
a good one to try is \texttt{w4-z3}.
|
|
|
|
The Cryptol REPL has some settings to control how floating point numbers
|
|
are printed on the REPL. In particular \texttt{:fp-base} specifies
|
|
in what numeric base to output floating point numbers, while
|
|
\texttt{:fp-format} provides various settings for formatting the
|
|
results. For more information, see \texttt{:help :set fp-format}.
|
|
|
|
|
|
%=====================================================================
|
|
% \section{Tuples: Heterogeneous collections}
|
|
% \label{sec:tuple}
|
|
\sectionWithAnswers{Tuples: Heterogeneous collections}{sec:tuple}
|
|
|
|
A tuple is a simple ordered collection of arbitrary values with
|
|
arbitrary types.\indTheTupleType Tuples are written with parentheses
|
|
surrounding two or more comma-separated elements. Cryptol also
|
|
supports a special zero-element tuple, written
|
|
\texttt{()}.\footnote{There is no syntax for tuples with exactly one
|
|
element. Writing parentheses around a single value does not make a
|
|
tuple; it denotes the same value with the same type.}
|
|
|
|
Tuple types have syntax similar to tuple values. They are written with
|
|
parentheses around two or more comma-separated types. Values of a
|
|
tuple type are tuples of the same length, where the value in each
|
|
position has the corresponding type. For example, type \texttt{([8],
|
|
Bit)} comprises pairs whose first element is an 8-bit word, and whose
|
|
second element is a bit. The empty tuple \texttt{()} is the only value
|
|
of type \texttt{()}.
|
|
|
|
\begin{Exercise}\label{ex:tup:1}
|
|
Try out the following tuples:
|
|
\begin{Verbatim}
|
|
(1, 2+4)
|
|
(True, False, True ^ False)
|
|
((1, 2), False, (3-1, (4, True)))
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:tup:1}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
(1, 6)
|
|
(True, False, True)
|
|
((1, 2), False, (2, (4, True)))
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\todo[inline]{Reflect upon these computed expressions. What is the
|
|
operational semantics of computation of constant-valued arithmetic
|
|
expressions? There seems to be differing behavior between
|
|
object-level and type-level expressions, but also differing
|
|
semantics at the object level in different contexts.}
|
|
|
|
\paragraph*{Projecting values from tuples} Use a \texttt{.} followed by
|
|
$n$ to project the $n+1$-th component of a tuple. Nested projections
|
|
are also supported. Note that projections cannot be used with the
|
|
empty tuple, as it has no components to project.
|
|
|
|
\begin{Exercise}\label{ex:tup:2}
|
|
Try out the following examples:
|
|
\begin{Verbatim}
|
|
(1, 2+4).0
|
|
(1, 2+4).1
|
|
((1, 2), False, (3-1, (4, True))).2.1
|
|
\end{Verbatim}
|
|
Write a nested projection to extract the value \texttt{True} from the
|
|
expression:
|
|
\begin{Verbatim}
|
|
((1, 2), (2, 6, (True, 4)), False)
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:tup:2}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
Cryptol> (1, 2+4).0
|
|
1
|
|
Cryptol> (1, 2+4).1
|
|
6
|
|
Cryptol> ((1, 2), False, (3-1, (4, True))).2.1
|
|
(4, True)
|
|
\end{Verbatim}
|
|
The required expression would be:
|
|
\begin{Verbatim}
|
|
((1, 2), (2, 6, (True, 4)), False).1.2.0
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\begin{tip}
|
|
While tuple projections can come in handy, we rarely see them used
|
|
in Cryptol programs. As we shall see later, Cryptol's powerful
|
|
pattern-matching mechanism provides a much nicer and usable
|
|
alternative for extracting parts of tuples and other composite data
|
|
values.
|
|
\end{tip}
|
|
|
|
%=====================================================================
|
|
% \section{Sequences: Homogeneous collections}
|
|
% \label{sec:sequences}
|
|
\sectionWithAnswers{Sequences: Homogeneous collections}{sec:sequences}
|
|
|
|
While tuples contain heterogeneous data, sequences are used for
|
|
homogeneous collections of values, akin to value arrays in more
|
|
traditional languages. A sequence contains elements of any
|
|
\emph{single} type, even sequences themselves, arbitrarily nested. We
|
|
simply write a sequence by enclosing it within square brackets with
|
|
comma-separated elements.\indTheSequenceType
|
|
|
|
\todo[inline]{Mention sequence types, syntax}
|
|
|
|
\begin{Exercise}\label{ex:seq:1}
|
|
Try out the following sequences:
|
|
\begin{Verbatim}
|
|
[1, 2]
|
|
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
|
\end{Verbatim}
|
|
Note how the latter example can be used as the representation of a
|
|
$3\times3$ matrix.
|
|
\end{Exercise}
|
|
|
|
\begin{tip}
|
|
The most important thing to remember about a sequence is that its
|
|
elements must be of exactly the same type.
|
|
\end{tip}
|
|
|
|
\begin{Exercise}\label{ex:seq:2}
|
|
Type in the following expressions to Cryptol and observe the
|
|
type errors:
|
|
\begin{Verbatim}
|
|
[True, [True]]
|
|
[[1, 2, 3], [4, 5]]
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:2}
|
|
In each case we get a type error:
|
|
\begin{Verbatim}
|
|
Cryptol> [True, [True]]
|
|
[error] at <interactive>:1:8--1:14:
|
|
Type mismatch:
|
|
Expected type: Bit
|
|
Inferred type: [1]
|
|
Cryptol> [[1, 2, 3], [4, 5]]
|
|
[error] at <interactive>:1:13--1:19:
|
|
Type mismatch:
|
|
Expected type: 3
|
|
Inferred type: 2
|
|
\end{Verbatim}
|
|
In the first case, we are trying to put a bit (\texttt{True}) and a
|
|
singleton sequence containing a bit (\texttt{[True]}) in the same
|
|
sequence, which have different types. In the second case, we are
|
|
trying to put two sequences of different lengths into a sequence,
|
|
which again breaks the homogeneity requirement.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Enumerations}\indEnum
|
|
\label{sec:enumerations}
|
|
|
|
Cryptol enumerations allow us to write sequences more compactly,
|
|
instead of listing the elements individually. An enumeration is a
|
|
means of writing a sequence by providing a (possibly infinite) range.
|
|
Cryptol enumerations are not equivalent to mainstream programming
|
|
languages' notions of enumeration types, other than both kinds of
|
|
constructs guarantee that enumeration elements are distinct.
|
|
|
|
\begin{Exercise}\label{ex:seq:3}
|
|
Explore various ways of constructing enumerations in Cryptol, by
|
|
using the following expressions:
|
|
\begin{Verbatim}
|
|
[1 .. 10] // increment with step 1
|
|
[1, 3 .. 10] // increment with step 2 (= 3-1)
|
|
[10, 9 .. 1] // decrement with step 1 (= 10-9)
|
|
[10, 9 .. 20] // decrement with step 1 (= 10-9)
|
|
[10, 7 .. 1] // decrement with step 3 (= 10-7)
|
|
[10, 11 .. 1] // increment with step 1
|
|
[1 .. 10 : [8]] // increment 8-bit words with step 1
|
|
[1, 3 .. 10 : [16]] // increment 16-bit words with step 2 (= 3-1)
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:3}
|
|
Here are the responses from Cryptol:
|
|
\begin{Verbatim}
|
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
[1, 3, 5, 7, 9]
|
|
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
|
|
[]
|
|
[10, 7, 4, 1]
|
|
[]
|
|
\end{Verbatim}
|
|
Note how \texttt{[10, 11 ..\ 1]} and \texttt{[10, 9 ..\ 20]} give us empty
|
|
sequences, since the upper bound is smaller than the lower bound in
|
|
the former, and larger in the latter.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Comprehensions}\indComp
|
|
\label{sec:comprehensions}
|
|
|
|
A Cryptol comprehension is a way of programmatically computing the
|
|
elements of a new sequence, out of the elements of existing
|
|
ones.\indComp The syntax is reminiscent of the set comprehension
|
|
notation from ordinary mathematics, generalized to cover parallel
|
|
branches (as explained in the exercises below). Note that Cryptol
|
|
comprehensions are not generalized numeric comprehensions (like
|
|
summation, product, maximum, or minimum), though such comprehensions
|
|
can certainly be defined using Cryptol comprehensions.
|
|
|
|
\begin{Exercise}\label{ex:seq:4}
|
|
The components of a Cryptol sequence comprehension are an expression
|
|
of one or more variables (which defines each element of the
|
|
sequence), followed by one or more \emph{branches}, each preceded by
|
|
a vertical bar, which define how the variables' values are
|
|
generated. A comprehension with a single branch is called a
|
|
\emph{cartesian comprehension}. We can have one or more components
|
|
in a cartesian comprehension. Experiment with the following
|
|
expressions:\indComp\indCartesian
|
|
\begin{Verbatim}
|
|
[ (x, y) | x <- [1 .. 3], y <- [4, 5] ]
|
|
[ x + y | x <- [1 .. 3], y <- [] ]
|
|
[ (x + y, z) | x <- [1, 2], y <- [1], z <- [3, 4] ]
|
|
\end{Verbatim}
|
|
What is the number of elements in the resulting sequence, with respect
|
|
to the sizes of components?
|
|
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:4}
|
|
Here are the responses from Cryptol:
|
|
\begin{Verbatim}
|
|
[(1, 4) (1, 5) (2, 4) (2, 5) (3, 4) (3, 5)]
|
|
[]
|
|
[(2, 3) (2, 4) (3, 3) (3, 4)]
|
|
\end{Verbatim}
|
|
The size of the result will be the sizes of the components
|
|
multiplied. For instance, in the first example, the generator
|
|
\texttt{x <- [1 ..\ 3]} assigns 3 values to \texttt{x}, and the generator
|
|
\texttt{y <- [4, 5]} assigns 2 values to \texttt{y}; and hence the result has
|
|
$2\times 3 = 6$ elements.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:seq:5}\indParallel\indComp
|
|
A comprehension with multiple branches is called a \emph{parallel
|
|
comprehension}. We can have any number of parallel branches. The
|
|
contents of each branch will be \emph{zipped} to obtain the results.
|
|
Experiment with the following expressions:
|
|
\begin{Verbatim}
|
|
[ (x, y) | x <- [1 .. 3] | y <- [4, 5] ]
|
|
[ x + y | x <- [1 .. 3] | y <- [] ]
|
|
[ (x + y, z) | x <- [1, 2] | y <- [1] | z <- [3, 4] ]
|
|
\end{Verbatim}
|
|
What is the number of elements in the resulting sequence, with respect
|
|
to the sizes of the parallel branches?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:5}
|
|
Here are the responses from Cryptol:
|
|
\begin{Verbatim}
|
|
[(1, 4) (2, 5)]
|
|
[]
|
|
[(2, 3)]
|
|
\end{Verbatim}
|
|
In this case, the size of the result will be the minimum of the
|
|
component sizes. For the first example, the generator
|
|
\texttt{x <- [1 ..\ 3]} assigns 3 values to \texttt{x}, and the generator
|
|
\texttt{y <- [4, 5]} assigns 2 values to \texttt{y}; and hence the result has
|
|
$\min(2,3) = 2$ elements.
|
|
\end{Answer}
|
|
|
|
\begin{tip}
|
|
One can mix parallel and cartesian comprehensions, where each
|
|
parallel branch can contain multiple cartesian
|
|
generators.\indComp\indCartesian\indParallel
|
|
\end{tip}
|
|
|
|
\begin{tip}
|
|
While Cryptol comprehensions \emph{look} like standard mathematical
|
|
comprehensions, one must remember that the codomain of Cryptol
|
|
comprehensions is a sequence type of some kind, \emph{not} a set.
|
|
\end{tip}
|
|
|
|
Comprehensions may be nested.\indNestedComp In this pattern, the
|
|
element value expression of the outer nesting is a sequence
|
|
comprehension (which may refer to values generated by the outer
|
|
generator). The pattern looks like this:
|
|
|
|
\begin{minipage}{\textwidth} %% trying to avoid splitting this across pages
|
|
\begin{Verbatim}
|
|
[ [ <expr with x & y> // \
|
|
| y <- [1 .. 5] // inner generator -- outer
|
|
] / elements
|
|
| x <- [1 .. 5] // outer generator
|
|
]
|
|
\end{Verbatim}
|
|
\end{minipage}
|
|
|
|
\begin{Exercise}\label{ex:seq:6}
|
|
Use a nested comprehension to write an expression to produce a
|
|
$3\times3$ matrix (as a sequence of sequences), such that the $ij$th
|
|
entry contains the value {\tt (i, j)}.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:6}
|
|
Here is one way of writing such an expression, laid out in multiple
|
|
lines to show the structure:
|
|
\begin{Verbatim}
|
|
[ [ (i, j) | j <- [1 .. 3] ]
|
|
| i <- [1 .. 3]
|
|
]
|
|
produces:
|
|
[[(1, 1), (1, 2), (1, 3)],
|
|
[(2, 1), (2, 2), (2, 3)],
|
|
[(3, 1), (3, 2), (3, 3)]]
|
|
\end{Verbatim}
|
|
The outer comprehension is a comprehension (and hence is nested). In
|
|
particular the expression is:
|
|
\begin{Verbatim}
|
|
[ (i, j) | j <- [1 .. 3] ]
|
|
\end{Verbatim}
|
|
You can enter the whole expression in Cryptol all in one line, or
|
|
recall that you can put \texttt{\textbackslash} at line ends to continue to
|
|
the next line.\indLineCont If you are writing such an expression in a
|
|
program file, then you can lay it out as shown above or however most
|
|
makes sense to you.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Appending and indexing}
|
|
\label{sec:appending-indexing}
|
|
|
|
For sequences, the two basic operations are appending\indAppend
|
|
(\texttt{\#}) and selecting\indIndex elements out (\texttt{@},
|
|
\texttt{@@}, \texttt{!}, and \texttt{!!}). The forward selection
|
|
operator (\texttt{@}) starts counting from the beginning, while the
|
|
backward selection operator\indRIndex (\texttt{!}) starts from the
|
|
end. Indexing always starts at zero: that is, \texttt{xs @ 0} is the
|
|
first element of \texttt{xs}, while \texttt{xs !\ 0} is the last. The
|
|
permutation\indIndexs versions\indRIndexs (\texttt{@@} and
|
|
\texttt{!!}, respectively) allow us to concisely select multiple
|
|
elements: they allow us to extract elements in any order (which makes
|
|
them very useful for permuting sequences).
|
|
|
|
\todo[inline]{Cite other languages that express permutations like this?}
|
|
|
|
\begin{Exercise}\label{ex:seq:7}
|
|
Try out the following Cryptol expressions:
|
|
\begin{Verbatim}
|
|
[] # [1, 2]
|
|
[1, 2] # []
|
|
[1 .. 5] # [3, 6, 8]
|
|
[0 .. 9] @ 0
|
|
[0 .. 9] @ 5
|
|
[0 .. 9] @ 10
|
|
[0 .. 9] @@ [3, 4]
|
|
[0 .. 9] @@ []
|
|
[0 .. 9] @@ [9, 12]
|
|
[0 .. 9] @@ [9, 8 .. 0]
|
|
[0 .. 9] ! 0
|
|
[0 .. 9] ! 3
|
|
[0 .. 9] !! [3, 6]
|
|
[0 .. 9] !! [0 .. 9]
|
|
[0 .. 9] ! 12
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:7}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
Cryptol> :set warnDefaulting=off
|
|
Cryptol> [] # [1, 2]
|
|
[1, 2]
|
|
Cryptol> [1, 2] # []
|
|
[1, 2]
|
|
Cryptol> [1 .. 5] # [3, 6, 8]
|
|
[1, 2, 3, 4, 5, 3, 6, 8]
|
|
Cryptol> [0 .. 9] @ 0
|
|
0
|
|
Cryptol> [0 .. 9] @ 5
|
|
5
|
|
Cryptol> [0 .. 9] @ 10
|
|
invalid sequence index: 10
|
|
Cryptol> [0 .. 9] @@ [3, 4]
|
|
[3, 4]
|
|
Cryptol> [0 .. 9] @@ []
|
|
[]
|
|
Cryptol> [0 .. 9] @@ [9, 12]
|
|
invalid sequence index: 12
|
|
Cryptol> [0 .. 9] @@ [9, 8 .. 0]
|
|
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
|
Cryptol> [0 .. 9] ! 0
|
|
9
|
|
Cryptol> [0 .. 9] ! 3
|
|
6
|
|
Cryptol> [0 .. 9] !! [3, 6]
|
|
[6, 3]
|
|
Cryptol> [0 .. 9] !! [0 .. 9]
|
|
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
|
Cryptol> [0 .. 9] ! 12
|
|
invalid sequence index: 12
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:seq:8}
|
|
The permutation operators ({\tt @@} and {\tt !!}) can be defined
|
|
using sequence comprehensions. Write an expression that selects the
|
|
even indexed elements out of the sequence \texttt{[0 ..\ 10]} first
|
|
using {\tt @@}, and then using a sequence comprehension.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:8}
|
|
Using a permutation operator, we can simply write:
|
|
\begin{Verbatim}
|
|
[0 .. 10] @@ [0, 2 .. 10]
|
|
\end{Verbatim}
|
|
Using a comprehension, we can express the same idea using:
|
|
\begin{Verbatim}
|
|
[ [0 .. 10] @ i | i <- [0, 2 .. 10] ]
|
|
\end{Verbatim}
|
|
Strictly speaking, permutation operations are indeed redundant.
|
|
However, they lead to more concise and easier-to-read expressions.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Finite and infinite sequences}\indFiniteSeq\indInfSeq
|
|
\label{sec:finite-infin-sequ}
|
|
|
|
So far we have only seen finite sequences. An infinite sequence is one
|
|
that has an infinite number of elements, corresponding to
|
|
streams.\indStream Cryptol supports infinite sequences, where the
|
|
elements are accessed \emph{on demand}. This implies that Cryptol will
|
|
\emph{not} go into an infinite loop just because you have created an
|
|
infinite sequence: it will lazily construct the sequence and make its
|
|
elements available as demanded by the program.
|
|
|
|
\begin{Exercise}\label{ex:seq:9}
|
|
Try the following infinite enumerations:
|
|
\begin{Verbatim}
|
|
[1:[32] ...]
|
|
[1:[32], 3 ...]
|
|
[1:[32] ...] @ 2000
|
|
[1:[32], 3 ...] @@ [300, 500, 700]
|
|
[100, 102 ...]
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:9}
|
|
When you type in an infinite sequence, Cryptol will only print the
|
|
first 5 elements of it and will indicate that it is an infinite value
|
|
by putting $\ldots$ at the end.\footnote{You can change this behavior
|
|
by setting the {\tt infLength} variable, like so: {\tt Cryptol>
|
|
:set infLength=10} will show the first 10 elements of infinite
|
|
sequences} Here are the responses:
|
|
\begin{Verbatim}
|
|
[1, 2, 3, 4, 5, ...]
|
|
[1, 3, 5, 7, 9, ...]
|
|
2001
|
|
[601, 1001, 1401]
|
|
[100, 102, 104, 106, 108, ...]
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
\note{We are explicitly telling Cryptol to use 32-bit words
|
|
as the elements. The reason for doing so will become clear when we
|
|
study arithmetic shortly.}
|
|
\begin{Exercise}\label{ex:seq:10}
|
|
What happens if you use the reverse index operator ({\tt !}) on an
|
|
infinite sequence? Why?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:10}
|
|
Here is a simple test case:
|
|
\begin{Verbatim}
|
|
Cryptol> [1:[32] ...] ! 3
|
|
|
|
[error] at <interactive>:1:1--1:17:
|
|
Expected a finite type, but found `inf`.
|
|
\end{Verbatim}
|
|
The error message is telling us that we \emph{cannot} apply the reverse
|
|
index operator ({\tt !}) on an infinite sequence (\texttt{inf}). This
|
|
is a natural consequence of the fact that one can never reach the end
|
|
of an infinite sequence to count backwards. It is important to
|
|
emphasize that this is a \emph{type error}, i.e., the user gets this
|
|
message at compile time; instead of Cryptol going into an infinite
|
|
loop to reach the end of an infinite sequence.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Manipulating sequences}
|
|
\label{sec:manip-sequ}
|
|
|
|
Sequences are at the heart of Cryptol, and there are a number of
|
|
built-in functions for manipulating them in various ways. It is
|
|
worthwhile to try the following exercises to gain basic familiarity
|
|
with the basic operations.
|
|
|
|
\begin{Exercise}\label{ex:seq:11}
|
|
Try the following expressions:\indTake\indDrop\indSplit\indGroup\indJoin\indTranspose
|
|
\begin{Verbatim}
|
|
take`{3} [1 .. 12]
|
|
drop`{3} [1 .. 12]
|
|
split`{3} [1 .. 12]
|
|
groupBy`{3} [1 .. 12]
|
|
join [[1 .. 4], [5 .. 8], [9 .. 12]]
|
|
join [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
|
|
transpose [[1, 2, 3, 4], [5, 6, 7, 8]]
|
|
transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
|
\end{Verbatim}
|
|
And for fun, think about what these should produce:
|
|
\begin{Verbatim}
|
|
join [1,1]
|
|
transpose [1,2]
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:11}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
Cryptol> take`{3} [1 .. 12]
|
|
[1, 2, 3]
|
|
Cryptol> drop`{3} [1 .. 12]
|
|
[4, 5, 6, 7, 8, 9, 10, 11, 12]
|
|
Cryptol> split`{3}[1 .. 12]
|
|
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
|
|
Cryptol> groupBy`{3} [1 .. 12]
|
|
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
|
|
Cryptol> join [[1 .. 4], [5 .. 8], [9 .. 12]]
|
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
|
Cryptol> join [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
|
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
|
Cryptol> transpose [[1, 2, 3, 4], [5, 6, 7, 8]]
|
|
[[1, 5], [2, 6], [3, 7], [4, 8]]
|
|
Cryptol> transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
|
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
|
\end{Verbatim}
|
|
And for the fun bonus problems:
|
|
\begin{Verbatim}
|
|
Cryptol> join [1,1]
|
|
Showing a specific instance of polymorphic result:
|
|
* Using '1' for type argument 'each' of 'Cryptol::join'
|
|
3
|
|
Cryptol> transpose [1,2]
|
|
Showing a specific instance of polymorphic result:
|
|
* Using '2' for type argument 'cols' of 'Cryptol::transpose'
|
|
[1, 2]
|
|
\end{Verbatim}
|
|
The argument to \texttt{join} must be a sequence of sequences, so each
|
|
\texttt{1} must have a bitvector type. Cryptol defaults to the
|
|
smallest possible type, \texttt{[1]}. So \texttt{join [1,1]} becomes
|
|
\texttt{join [[True], [True]]}, which equals \texttt{[True, True]}, or
|
|
\texttt{3}.
|
|
|
|
With \texttt{transpose}, Cryptol similarly chooses the smallest
|
|
possible bitvector type \texttt{[2]} for the sequence elements. Then
|
|
\texttt{[1,2]} becomes \texttt{[[False, True], [True, False]]}, which
|
|
transposes to the same value.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:seq:12}
|
|
Based on your intuitions from the previous exercise, derive laws
|
|
between the following pairs of functions: {\tt take} and {\tt drop};
|
|
{\tt join} and {\tt split}; {\tt join} and {\tt groupBy}; {\tt
|
|
split} and {\tt groupBy} and {\tt transpose} and itself. For
|
|
instance, {\tt take} and {\tt drop} satisfy the following
|
|
equality:\indTake\indDrop\indJoin\indSplit\indGroup\indTranspose
|
|
\begin{Verbatim}
|
|
(take`{n} xs) # (drop`{n} xs) == xs
|
|
\end{Verbatim}
|
|
whenever {\tt n} is between {\tt 0} and the length of the sequence
|
|
{\tt xs}. Note that there might be multiple laws these functions
|
|
satisfy.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:12}
|
|
The following equalities are the simplest
|
|
candidates:\indJoin\indSplit\indGroup\indTranspose
|
|
\begin{Verbatim}
|
|
join (split`{parts=n} xs) == xs
|
|
join (groupBy`{each=n} xs) == xs
|
|
split`{parts=n} xs == groupBy`{each=m} xs
|
|
transpose (transpose xs) == xs
|
|
\end{Verbatim}
|
|
In the first two equalities {\tt n} must be a divisor of the length of
|
|
the sequence {\tt xs}. In the third equation, {\tt n} $\times$ {\tt m}
|
|
must equal the length of the sequence {\tt xs}.
|
|
\todo[inline]{These are theorems that should be part of the prelude!}
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:seq:13}
|
|
What is the relationship between the append operator {\tt \#} and {\tt
|
|
join}?\indAppend\indJoin
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:13}
|
|
Append ({\tt \#})\indAppend\indJoin joins two sequences of arbitrary
|
|
length, while {\tt join} appends a sequence of equal length
|
|
sequences. In particular, the equality:
|
|
\begin{Verbatim}
|
|
join [xs0, xs1, xs2, .. xsN] = xs0 # xs1 # xs2 ... # xsN
|
|
\end{Verbatim}
|
|
holds for all equal length sequences {\tt xs0}, {\tt xs1}, $\ldots$,
|
|
{\tt xsN}.
|
|
\end{Answer}
|
|
|
|
\paragraph*{Type-directed splits} The Cryptol primitive function {\tt
|
|
split}\indSplit splits a sequence into any number of equal-length
|
|
parts. An explicit result type is often used with {\tt split}, since
|
|
the number of parts and the number of elements in each part are not
|
|
given as arguments, but are determined by the type of the argument
|
|
sequence and the result context.
|
|
\begin{Verbatim}
|
|
Cryptol> split [1..12] : [1][12][8]
|
|
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
|
|
Cryptol> split [1..12] : [2][6][8]
|
|
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
|
|
Cryptol> split [1..12] : [3][4][8]
|
|
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
|
|
\end{Verbatim}
|
|
Here is what happens if we do {\em not} give an explicit signature on
|
|
the result:\indSignature
|
|
\begin{Verbatim}
|
|
Cryptol> split [1..12]
|
|
Cannot evaluate polymorphic value.
|
|
Type: {n, m, a} (n * m == 12, Literal 12 a, fin m) => [n][m]a
|
|
Cryptol> :t split [1..12]
|
|
split [1 .. 12] : {n, m, a} (n * m == 12, Literal 12 a, fin m) =>
|
|
[n][m]a
|
|
\end{Verbatim}
|
|
%% cryptol 1 said: : {a b c} (fin c,c >= 4,a*b == 12) => [a][b][c]
|
|
|
|
A complex type signature like this one first defines a set of type
|
|
variables \verb|{n, m, a}|, a set of constraints on those variables
|
|
\verb|(n * m == 12, Literal 12 a, fin m)|, a \texttt{=>} and finally
|
|
the shape description. In this case, Cryptol's \texttt{[n][m]a} is
|
|
telling us that the result will be a sequence of \texttt{n} things,
|
|
each of which is a sequence of \texttt{m} things, each of which is a
|
|
value of type \texttt{a}. The \texttt{Literal} constraint tells us
|
|
that \texttt{a} is a type that can represent numbers (at least) up to
|
|
12. The other constraints are that \texttt{n * m == 12}, which means
|
|
we should completely cover the entire input, and that the length
|
|
\texttt{m} needs to be finite. As you can see, \texttt{split} is a
|
|
very powerful function. The flexibility afforded by \texttt{split}
|
|
comes in very handy in Cryptol. We shall see one example of its usage
|
|
later in \autoref{sec:scytale}.
|
|
|
|
\begin{Exercise}\label{ex:split:0}
|
|
With a sequence of length 12, as in the above example, there are
|
|
precisely 6 ways of splitting it: 1 $\times$ 12, 2 $\times$ 6, 3
|
|
$\times$ 4, 4 $\times$ 3, 6 $\times$ 2, and 12 $\times$ 1. We have
|
|
seen the first three splits above. Write the expressions
|
|
corresponding to the latter three.\indSplit
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:split:0}
|
|
Here they are:\indSplit
|
|
\begin{Verbatim}
|
|
Cryptol> split [1..12] : [4][3][8]
|
|
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
|
|
Cryptol> split [1..12] : [6][2][8]
|
|
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
|
|
Cryptol> split [1..12] : [12][1][8]
|
|
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]]
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:split:1}
|
|
What happens when you type
|
|
\texttt{split [1 ..\ 12] :\ [5][2][8]}?\indSplit
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:split:1}
|
|
Cryptol will issue a type error:\indSplit
|
|
\begin{Verbatim}
|
|
Cryptol> split [1..12] : [5][2][8]
|
|
[error] at <interactive>:1:7--1:14:
|
|
Type mismatch:
|
|
Expected type: 10
|
|
Inferred type: 12
|
|
\end{Verbatim}
|
|
Cryptol is telling us that we have requested 10 elements in the final
|
|
result (5 $\times$ 2), but the input has 12.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:split:2}
|
|
Write a \texttt{split} expression to turn the sequence \texttt{[1 ..\ 120]
|
|
:\ [120][8]} into a nested sequence with type {\tt [3][4][10][8]},
|
|
keeping the elements in the same order.\indSplit \lhint{Use nested
|
|
comprehensions.} \indComp
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:split:2}
|
|
We can split\indSplit 120 elements first into 3 $\times$ 40, splitting each
|
|
of the the elements ({\tt level1} below) into 4 $\times$ 10. A nested
|
|
comprehension fits the bill:\indComp
|
|
\begin{Verbatim}
|
|
[ split level1 : [4][10][8]
|
|
| level1 <- split ([1 .. 120] : [120][8]) : [3][40][8]
|
|
]
|
|
\end{Verbatim}
|
|
(Note again that you can enter the above in the command line all in
|
|
one line, or by putting the line continuation character
|
|
\texttt{\textbackslash} at the end of the first two
|
|
lines.)\indLineCont \todo[inline]{You don't need nested
|
|
comprehensions: \texttt{split (split [1..120]) :\ [3][4][10][8]}
|
|
also works.}
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Shifts and rotates}
|
|
\label{sec:shifts-rotates}
|
|
|
|
Common operations on sequences include shifting and rotating them.
|
|
Cryptol supports both versions with left/right
|
|
variants.\indShiftLeft\indShiftRight\indRotLeft\indRotRight
|
|
\begin{Exercise}\label{ex:seq:14}
|
|
Experiment with the following expressions:
|
|
\begin{Verbatim}
|
|
[1, 2, 3, 4, 5] >> 2
|
|
[1, 2, 3, 4, 5] >> 10
|
|
[1, 2, 3, 4, 5] << 2
|
|
[1, 2, 3, 4, 5] << 10
|
|
[1, 2, 3, 4, 5] >>> 2
|
|
[1, 2, 3, 4, 5] >>> 10
|
|
[1, 2, 3, 4, 5] <<< 2
|
|
[1, 2, 3, 4, 5] <<< 10
|
|
\end{Verbatim}
|
|
\noindent Notice that shifting/rotating always returns a sequence
|
|
precisely the same size as the original.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:14}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
[0, 0, 1, 2, 3]
|
|
[0, 0, 0, 0, 0]
|
|
[3, 4, 5, 0, 0]
|
|
[0, 0, 0, 0, 0]
|
|
[4, 5, 1, 2, 3]
|
|
[1, 2, 3, 4, 5]
|
|
[3, 4, 5, 1, 2]
|
|
[1, 2, 3, 4, 5]
|
|
\end{Verbatim}
|
|
\todo[inline]{Reflections on this exercise?}
|
|
\end{Answer}
|
|
\begin{Exercise}\label{ex:seq:15}
|
|
Let {\tt xs} be a sequence of length $n$. What is the result of
|
|
rotating {\tt xs} left or right by a multiple of $n$?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:seq:15}
|
|
Rotating (left or right) by a multiple of the size of a sequence
|
|
will leave it unchanged.
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Words revisited}
|
|
% \label{sec:words2}
|
|
\sectionWithAnswers{Words as sequences}{sec:words2}
|
|
|
|
In \autoref{sec:words} we have introduced numbers as a distinct value
|
|
type in Cryptol. In fact, a number in Cryptol is nothing but a finite
|
|
sequence of bits, so words are not a separate type. For instance, the
|
|
literal expression \texttt{42:[6]} is precisely the same as the
|
|
bit-sequence \texttt{[True, False, True, False, True,
|
|
False]}.\indTheWordType The type \texttt{[6]} is really just an
|
|
abbreviation for \texttt{[6]Bit}.
|
|
|
|
\begin{Exercise}\label{ex:words:0}
|
|
Explain why {\tt 42} is the same as {\tt [True, False, True, False,
|
|
True, False]}. Is Cryptol little-endian, or
|
|
big-endian?\indEndianness
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:words:0}
|
|
Cryptol is big-endian,\indEndianness meaning that the
|
|
most-significant-bit comes first. In the sequence {\tt [True, False,
|
|
True, False, True, False]}, the first element corresponds to the
|
|
most-significant-digit, i.e., $2^5$, the next element corresponds to
|
|
the coefficient of $2^4$, etc. A {\tt False} bit yields a
|
|
coefficient of $0$ and a {\tt True} bit gives $1$. Hence, we have:
|
|
$$1\times2^5 + 0\times2^4 + 1\times2^3 + 0\times2^2 + 1\times2^1 + 0\times2^0 = 32 + 0 + 8 + 0 + 2 + 0 = 42$$
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:words:1}
|
|
Try out the following words: \lhint{It might help to use {\tt :set
|
|
base=2} to see the bit patterns.}\indSettingBase
|
|
\begin{Verbatim}
|
|
12:[4]
|
|
12 # [False]
|
|
[False, False] # 12
|
|
[True, False] # 12
|
|
12 # [False, True]
|
|
32:[6]
|
|
12 # 32
|
|
[True, False, True, False, True, False] == 42
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:words:1}
|
|
After issuing {\tt :set base=2}, here are Cryptol's
|
|
responses:\indSettingBase
|
|
\begin{Verbatim}
|
|
0b1100
|
|
0b11000
|
|
0b1100
|
|
0b101100
|
|
0b110001
|
|
0b100000
|
|
0b1100100000
|
|
True
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:words:4}
|
|
Since words are sequences, the sequence functions from
|
|
\exerciseref{ex:seq:11} apply to words as well.
|
|
Try out the following examples and explain the outputs you
|
|
observe:\indTake\indDrop\indSplit\indGroup
|
|
\begin{Verbatim}
|
|
take`{3} 0xFF
|
|
take`{3} (12:[6])
|
|
drop`{3} (12:[6])
|
|
split`{3} (12:[6])
|
|
groupBy`{3} (12:[6])
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\noindent Recall that the notation {\tt 12:[6]} means the constant 12
|
|
with the type precisely 6 bits wide.
|
|
\begin{Answer}\ansref{ex:words:4}
|
|
Remember that Cryptol is big-endian\indEndianness and hence {\tt
|
|
12:[6]} is precisely {\tt [False, False, True, True, False,
|
|
False]}. Here are Cryptol's responses:\indTake
|
|
\begin{Verbatim}
|
|
Cryptol> take`{3} 0xFF
|
|
7
|
|
Cryptol> take`{3} (12:[6])
|
|
1
|
|
Cryptol> drop`{3} (12:[6])
|
|
4
|
|
Cryptol> split`{3} (12:[6])
|
|
[0, 3, 0]
|
|
Cryptol> groupBy`{3} (12:[6])
|
|
[1, 4]
|
|
\end{Verbatim}
|
|
For instance, the expression {\tt take`\{3\} (12:[6])} evaluates as follows:
|
|
\begin{Verbatim}
|
|
take`{3} (12:[6])
|
|
= take (3, [False, False, True, True, False, False])
|
|
= [False, False, True]
|
|
= 1
|
|
\end{Verbatim}
|
|
Follow similar lines of reasoning to justify the results for the
|
|
remaining expressions.
|
|
\end{Answer}
|
|
\begin{Exercise}\label{ex:words:5}
|
|
Try \exerciseref{ex:words:4}, this time with the constant {\tt
|
|
12:[12]}. Do any of the results change? Why?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:words:5}
|
|
Because of the leading zeros in {\tt 12:[12]}, they all produce
|
|
different results:\indTake\indDrop\indSplit\indGroup
|
|
\begin{Verbatim}
|
|
Cryptol> take`{3} (12:[12])
|
|
0
|
|
Cryptol> drop`{3} (12:[12])
|
|
12
|
|
Cryptol> split`{3} (12:[12])
|
|
[0, 0, 12]
|
|
Cryptol> groupBy`{3} (12:[12])
|
|
[0, 0, 1, 4]
|
|
\end{Verbatim}
|
|
We will show the evaluation steps for {\tt groupBy} here, and urge the
|
|
reader to do the same for {\tt split}:
|
|
\begin{Verbatim}
|
|
groupBy`{3} (12:[12])
|
|
= groupBy`{3} [False, False, False, False, False, False,
|
|
False, False, True, True, False, False]
|
|
= [[False, False, False], [False, False, False]
|
|
[False, False, True], [True, False, False]]
|
|
= [0, 0, 1, 4]
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\paragraph*{Shifts and rotates on words} Consider what happens if we
|
|
shift a word, say {\tt 12:[6]} by one to the right:
|
|
\indShiftLeft\indShiftRight\indRotLeft\indRotRight
|
|
\begin{Verbatim}
|
|
(12:[6]) >> 1
|
|
= [False, False, True, True, False, False] >> 1
|
|
= [False, False, False, True, True, False]
|
|
= 6
|
|
\end{Verbatim}
|
|
That is shifting right by one effectively divides the word by 2. This
|
|
is due to Cryptol's ``big-endian'' representation of
|
|
numbers.\footnote{This is a significant change from Cryptol version 1,
|
|
which interpreted the leftmost element of a sequence as the
|
|
lowest-ordered bit (and thus shifting right was multiplying by 2,
|
|
and shifting left was dividing by 2). The way it is handled now
|
|
matches the traditional
|
|
interpretation.}\indRotLeft\indRotRight\indShiftLeft\indShiftRight
|
|
|
|
\begin{Exercise}\label{ex:words:6}
|
|
Try the following examples of shifting/rotating words:
|
|
\begin{Verbatim}
|
|
(12:[8]) >> 2
|
|
(12:[8]) << 2
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:words:6}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
3
|
|
48
|
|
\end{Verbatim}
|
|
\todo[inline]{Reflect upon these responses.}
|
|
\end{Answer}
|
|
|
|
\todo[inline]{2.0: This is \textbf{NOT} architecture endianness; we
|
|
need a better discussion here. Dylan will do some code-diving on
|
|
Cryptol version 1.}
|
|
|
|
\paragraph*{Little-endian vs Big-endian} The discussion of endianness
|
|
comes up often in computer science, with no clear
|
|
winner.\indEndianness Since Cryptol allows indexing from the beginning
|
|
or the end of a (finite) sequence, you can access the 0th
|
|
(least-significant) bit of a sequence \texttt{k} with \texttt{k!0}, the 1st bit with
|
|
\texttt{k!1}, and so on.\indIndex
|
|
|
|
%=====================================================================
|
|
\section{Characters and strings}
|
|
\label{sec:charstring}
|
|
|
|
Strictly speaking Cryptol does {\em not} have characters and strings
|
|
as a separate type. However, Cryptol does allow characters in
|
|
programs, which simply correspond to their ASCII
|
|
equivalents. Similarly, strings are merely sequences of characters,
|
|
i.e., sequences of words.\indTheStringType\indTheCharType The
|
|
following examples illustrate:
|
|
\begin{Verbatim}
|
|
Cryptol> :set base=10
|
|
Cryptol> :set ascii=off
|
|
Cryptol> 'A'
|
|
65
|
|
Cryptol> "ABC"
|
|
[65, 66, 67]
|
|
Cryptol> :set ascii=on
|
|
Cryptol> "ABC"
|
|
"ABC"
|
|
Cryptol> :set ascii=off
|
|
Cryptol> ['A' .. 'Z']
|
|
[65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
|
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90]
|
|
Cryptol> :set ascii=on
|
|
Cryptol> ['A' .. 'Z']
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
\end{Verbatim}
|
|
\note{This is the reason why we have to use the {\tt :set ascii=on}
|
|
command to print ASCII strings. Otherwise, Cryptol will not have
|
|
enough information to tell numbers from
|
|
characters.\indSettingASCII}
|
|
|
|
\noindent Since characters are simply 8-bit words, you can do word
|
|
operations on them; including arithmetic:
|
|
\begin{Verbatim}
|
|
Cryptol> 'C' - 'A'
|
|
2
|
|
\end{Verbatim}
|
|
|
|
%=====================================================================
|
|
% \section{Records: Named collections}
|
|
% \label{sec:records}
|
|
\sectionWithAnswers{Records: Named collections}{sec:records}
|
|
|
|
In Cryptol, records are simply collections of named fields. In this
|
|
sense, they are very similar to tuples (\autoref{sec:tuple}), which
|
|
can be thought of records without field names. Like a tuple, the
|
|
fields of a record can be of any type. We construct records by listing
|
|
the fields inside curly braces, separated by commas. We project fields
|
|
out of a record with the usual dot-notation, similar to tuple
|
|
projections. Note that the order of fields in a record is
|
|
immaterial.\indTheRecordType\indTheTupleType
|
|
|
|
Record equality is defined in the standard fashion. Two records are
|
|
equal if they have the same number of fields, if their field names are
|
|
identical, if identically named fields are of comparable types and
|
|
have equal values.
|
|
|
|
\begin{Exercise}\label{ex:record:1}
|
|
Type in the following expressions and observe the output:
|
|
\begin{Verbatim}
|
|
{xCoord = 12:[32], yCoord = 21:[32]}
|
|
{xCoord = 12:[32], yCoord = 21:[32]}.yCoord
|
|
{name = "Cryptol", address = "Galois"}
|
|
{name = "Cryptol", address = "Galois"}.address
|
|
{name = "test", coords = {xCoord = 3:[32], yCoord = 5:[32]}}
|
|
{name = "test", coords = {xCoord = 3:[32], \
|
|
yCoord = 5:[32]}}.coords.yCoord
|
|
{x=True, y=False} == {y=False, x=True}
|
|
\end{Verbatim}
|
|
\noindent You might find the command {\tt :set
|
|
ascii=on}\indSettingASCII useful in viewing the output.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:record:1}
|
|
Here are Cryptol's responses:
|
|
\begin{small}
|
|
\begin{Verbatim}
|
|
Cryptol> {xCoord = 12:[32], yCoord = 21:[32]}
|
|
{xCoord = 12, yCoord = 21}
|
|
Cryptol> {xCoord = 12:[32], yCoord = 21:[32]}.yCoord
|
|
21
|
|
Cryptol> {name = "Cryptol", address = "Galois"}
|
|
{name = "Cryptol", address = "Galois"}
|
|
Cryptol> {name = "Cryptol", address = "Galois"}.address
|
|
"Galois"
|
|
Cryptol> {name = "test", coords = {xCoord = 3:[32], yCoord = 5:[32]}}
|
|
{name = "test", coords = {xCoord = 3, yCoord = 5}}
|
|
Cryptol> {name = "test", coords = {xCoord = 3:[32], \
|
|
yCoord = 5:[32]}}.coords.yCoord
|
|
5
|
|
Cryptol> {x=True, y=False} == {y=False, x=True}
|
|
True
|
|
\end{Verbatim}
|
|
\end{small}
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{\texorpdfstring{The {\tt zero}}{The zero}}
|
|
% \label{sec:zero}
|
|
\sectionWithAnswers{\texorpdfstring{The {\tt zero}}{The zero}}{sec:zero}
|
|
|
|
Before proceeding further, we have to take a detour and talk briefly
|
|
about one of the most useful values in Cryptol: {\tt zero}.\indZero
|
|
The value {\tt zero} inhabits every type in Cryptol.
|
|
The following examples should illustrate the idea:
|
|
\begin{Verbatim}
|
|
Cryptol> zero : Bit
|
|
False
|
|
Cryptol> zero : [8]
|
|
0
|
|
Cryptol> zero : Integer
|
|
0
|
|
Cryptol> zero : Z 19
|
|
0
|
|
Cryptol> zero : Rational
|
|
(ratio 0 1)
|
|
Cryptol> zero : ([8], Bit)
|
|
(0, False)
|
|
Cryptol> zero : [8][3]
|
|
[0, 0, 0, 0, 0, 0, 0, 0]
|
|
Cryptol> zero : [3](Bit, [4])
|
|
[(False, 0), (False, 0), (False, 0)]
|
|
Cryptol> zero : {xCoord : [12], yCoord : [5]}
|
|
{xCoord=0, yCoord=0}
|
|
\end{Verbatim}
|
|
|
|
\noindent On the other extreme, the value {\tt zero} combined with the
|
|
complement operator {\tt \Verb|~|}\indComplement gives us values that
|
|
consist of all {\tt True}\indTrue bits:
|
|
\begin{Verbatim}
|
|
Cryptol> ~zero : Bit
|
|
True
|
|
Cryptol> ~zero : [8]
|
|
255
|
|
Cryptol> ~zero : ([8], Bit)
|
|
(255, True)
|
|
Cryptol> ~zero : [8][3]
|
|
[7, 7, 7, 7, 7, 7, 7, 7]
|
|
Cryptol> ~zero : [3](Bit, [4])
|
|
[(True, 15), (True, 15), (True, 15)]
|
|
Cryptol> ~zero : {xCoord : [12], yCoord : [5]}
|
|
{xCoord=4095, yCoord=31}
|
|
\end{Verbatim}
|
|
|
|
\begin{Exercise}\label{ex:zero:0}
|
|
We said that {\tt zero} inhabits all types in Cryptol. This also
|
|
includes functions. What do you think the appropriate {\tt zero}
|
|
value for a function would be? Try out the following examples:
|
|
\begin{Verbatim}
|
|
(zero : ([8] -> [3])) 5
|
|
(zero : Bit -> {xCoord : [12], yCoord : [5]}) True
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:zero:0}
|
|
Here are Cryptol's responses:\indZero
|
|
\begin{Verbatim}
|
|
Cryptol> (zero : ([8] -> [3])) 5
|
|
0
|
|
Cryptol> (zero : Bit -> {xCoord : [12], yCoord : [5]}) True
|
|
{xCoord=0, yCoord=0}
|
|
\end{Verbatim}
|
|
The {\tt zero} function returns {\tt 0}, ignoring its argument.
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Arithmetic}
|
|
% \label{sec:arithmetic}
|
|
\sectionWithAnswers{Arithmetic}{sec:arithmetic}
|
|
|
|
Cryptol supports the usual binary arithmetic operators {\tt +}, {\tt
|
|
-}, {\tt *}, {\tt \Verb|^^|} (exponentiation), {\tt /} (integer
|
|
division), {\tt \%} (integer modulus), along with \emph{ceiling}
|
|
base-2 logarithm {\tt lg2} and binary {\tt min} and {\tt max}.
|
|
|
|
It is important thing to remember is that all arithmetic in Cryptol is
|
|
carried out according to the type of the values being computed;
|
|
for word types in particular, arithmetic is modular,\indModular
|
|
with respect to the underlying word size. As a
|
|
consequence, there is no such thing as an overflow/underflow in
|
|
Cryptol, as the result will be always guaranteed to fit in the
|
|
resulting word size. While this is very handy for most applications of
|
|
Cryptol, it requires some care if overflow has to be treated
|
|
explicitly.\indOverflow\indUnderflow\indPlus\indMinus\indTimes\indDiv\indMod\indLg\indMin\indMax\indExponentiate
|
|
|
|
\begin{Exercise}\label{ex:arith:1}
|
|
What is the value of \texttt{1 + 1 :~[\textunderscore]}? Surprised?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:1}
|
|
Since {\tt 1} requires only 1 bit to represent, the result also has
|
|
1 bit. In other words, the arithmetic is done modulo $2^1 =
|
|
2$. Therefore, {\tt 1+1 = 0}.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:2}
|
|
What is the value of \texttt{1 + 1 :~[8]}? Why?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:2}
|
|
Now we have 8 bits to work with, so the result is {\tt 2}. Since we
|
|
have 8 bits to work with, overflow will not happen until we get a
|
|
sum that is at least 256.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:3}
|
|
What is the value of \texttt{3 - 5 :~[\textunderscore]}? How about \texttt{3 - 5 :~[8]}?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:3}
|
|
Recall from \autoref{sec:words} that there are no negative
|
|
numbers in Cryptol. The values \texttt{3} and \texttt{5} can be
|
|
represented in 3 bits, so Cryptol uses 3 bits to represent the
|
|
result, so the arithmetic is done modulo $2^3=8$. Hence, the result
|
|
is \texttt{6}. In the second expression, we have 8 bits to work with,
|
|
so the modulus is $2^8 = 256$; so the subtraction results in
|
|
\texttt{254} (or \texttt{0xfe}).
|
|
\end{Answer}
|
|
|
|
\note{Cryptol supports subtraction both as a binary operator, and as a
|
|
unary operator. When used in a unary fashion (a.k.a. unary
|
|
minus),\indUnaryMinus it simply means subtraction from \texttt{0}.
|
|
For instance, \texttt{-5} precisely means \texttt{0-5}, and is subject to the
|
|
usual modular arithmetic rules.}\indModular\indMinus
|
|
|
|
\begin{Exercise}\label{ex:arith:4}
|
|
Try out the following expressions:\indEq\indNeq
|
|
\begin{Verbatim}
|
|
2 / 0
|
|
2 % 0
|
|
3 + (if 3 == 2+1 then 12 else 2/0)
|
|
3 + (if 3 != 2+1 then 12 else 2/0)
|
|
lg2 (-25) : [_]
|
|
\end{Verbatim}
|
|
In the last expression, remember that unary minus will\indUnaryMinus
|
|
be done in a modular fashion. What is the modulus used for this
|
|
operation?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:4}
|
|
The first, second, and fourth examples give a ``division by 0''
|
|
error message. In the third example, the division by zero occurs
|
|
only in an unreachable branch, so the result is not an error.
|
|
|
|
In the last expression, the number \texttt{25} fits in 5 bits, so
|
|
the modulus is $2^5 = 32$. The unary minus yields \texttt{7}, hence
|
|
the result is \texttt{3}. Note that \texttt{lg2} is the \emph{floor
|
|
log base 2} function.\indLg\indEq\indNeq
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:5:1}
|
|
Integral division truncates down. Try out the following expressions:\indDiv\indMod
|
|
\begin{Verbatim}
|
|
(6 / 3, 6 % 3)
|
|
(7 / 3, 7 % 3)
|
|
(8 / 3, 8 % 3)
|
|
(9 / 3, 9 % 3)
|
|
\end{Verbatim}
|
|
What is the relationship between {\tt /} and {\tt \%}?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:5:1}
|
|
Here are Cryptol's answers:\indDiv\indMod
|
|
\begin{Verbatim}
|
|
(2, 0)
|
|
(2, 1)
|
|
(2, 2)
|
|
(3, 0)
|
|
\end{Verbatim}
|
|
The following equation holds regarding {\tt /} and {\tt \%}:
|
|
$$
|
|
x = (x / y) * y + (x \% y)
|
|
$$
|
|
whenever $y \neq 0$.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:5}
|
|
What is the value of \texttt{min (5:[\textunderscore]) (-2)}? Why?
|
|
Why are the parentheses around \texttt{-2}
|
|
necessary?\indMin\indModular\indUnaryMinus
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:5}
|
|
The bit-width in this case is 3 (to accommodate for the number 5),
|
|
and hence arithmetic is done modulo $2^3 = 8$. Thus, {\tt -2}
|
|
evaluates to {\tt 6}, leading to the result {\tt min 5, (-2) == 5}.
|
|
The parentheses are necessary because unary negation is handled in
|
|
Cryptol's parser, not in its lexer, because whitespace is ignored.
|
|
If this were not the case, reflect upon how you would differentiate
|
|
the expressions \texttt{min 5 - 2} and \texttt{min 5 -2}.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:6}
|
|
How about {\tt max 5 (-2:[8])}? Why?\indMin\indModular\indUnaryMinus
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:6}
|
|
This time we are telling Cryptol to use precisely 8 bits, so {\tt
|
|
-2} is equivalent to {\tt 254}. Therefore the result is {\tt 254}.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:7}
|
|
Write an expression that computes the sum of two sequences
|
|
\texttt{[1..\ 10]} and \texttt{[10, 9 ..\ 1]}.\indPlus
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:7}
|
|
The idiomatic Cryptol way of summing two sequences is to use a
|
|
comprehension:\indComp
|
|
\begin{Verbatim}
|
|
[ i+j | i <- [1 .. 10]
|
|
| j <- [10, 9 .. 1]
|
|
]
|
|
\end{Verbatim}
|
|
However, you will notice that the following will work as well:
|
|
\begin{Verbatim}
|
|
[1 .. 10] + [10, 9 .. 1]
|
|
\end{Verbatim}
|
|
That is, Cryptol automatically lifts arithmetic operators to
|
|
sequences, element-wise. However, it is often best to keep the
|
|
explicit style of writing the comprehension, even though it is a bit
|
|
longer, since that makes it absolutely clear what the intention is and
|
|
how the new sequence is constructed, without depending implicitly
|
|
upon Cryptol's automatic lifting.\indArithLift
|
|
\end{Answer}
|
|
|
|
\paragraph*{Comparison operators} Cryptol supports the comparison
|
|
operators {\tt ==}, {\tt !=}, {\tt >}, {\tt >=}, {\tt <}, {\tt <=},
|
|
with their usual meanings.\indEq\indNeq\indGt\indGte\indLt\indLte
|
|
|
|
\begin{Exercise}\label{ex:arith:8}
|
|
Try out the following expressions:
|
|
\begin{Verbatim}
|
|
((2 >= 3) || (3 < 6)) && (4 == 5)
|
|
if 3 >= 2 then True else 1 < 12
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:8}
|
|
Here are Cryptol's responses:
|
|
\begin{Verbatim}
|
|
Cryptol> ((2 >= 3) || (3 < 6)) && (4 == 5)
|
|
False
|
|
Cryptol> if 3 >= 2 then True else 1 < 12
|
|
True
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\paragraph*{Enumerations, revisited} In
|
|
\exerciseref{ex:seq:9}, we wrote the infinite
|
|
enumeration{\indEnum\indInfSeq}starting at {\tt 1} using an explicit
|
|
type as follows:
|
|
\begin{Verbatim}
|
|
[(1:[32]) ...]
|
|
\end{Verbatim}
|
|
As expected, Cryptol evaluates this expression to:
|
|
\begin{Verbatim}
|
|
[1, 2, 3, 4, 5, ...]
|
|
\end{Verbatim}
|
|
However, while the output suggests that the numbers are increasing all
|
|
the time, that is just an illusion! Since the elements of this
|
|
sequence are 32-bit words, eventually they will wrap over, and go back
|
|
to 0. (In fact, this will happen precisely at the element $2^{32}-1$,
|
|
starting the count at 0 as usual.) We can observe this much more
|
|
simply, by using a smaller bit size for the constant {\tt 1}:
|
|
\begin{Verbatim}
|
|
Cryptol> [(1:[2])...]
|
|
[1, 2, 3, 0, 1 ...
|
|
Cryptol> take`{20} [(1:[2])...]
|
|
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
|
|
\end{Verbatim}
|
|
We still get an infinite sequence, but the numbers will repeat
|
|
themselves eventually. Note that this is a direct consequence of
|
|
Cryptol's modular arithmetic.\indModular
|
|
|
|
\todo[inline]{FIXME the next examples don't make sense any more.}
|
|
|
|
There is one more case to look at. What happens if we completely leave
|
|
out the bit-width?
|
|
\begin{Verbatim}
|
|
Cryptol> [1:[_] ...]
|
|
[1, 0, 1, 0, 1, ...]
|
|
\end{Verbatim}
|
|
In this case, Cryptol figured out that the number {\tt 1} requires
|
|
precisely 1 bit, and hence the arithmetic is done modulo $2^1 = 2$,
|
|
giving us the sequence $1,0,1,0,\ldots$ In particular, an
|
|
enumeration of the form:
|
|
\begin{Verbatim}
|
|
[k ...]
|
|
\end{Verbatim}
|
|
will be treated as if the user has written:
|
|
\begin{Verbatim}
|
|
[k, (k+1) ...]
|
|
\end{Verbatim}
|
|
and type inference will assign the smallest bit-size possible to
|
|
represent {\tt k}.
|
|
|
|
\begin{Exercise}\label{ex:arith:9}
|
|
Remember from \exerciseref{ex:decimalType} that the word \texttt{0}
|
|
requires 0 bits to represent. Based on this, what is the value of
|
|
the enumeration \texttt{[0:[\textunderscore], 1...]}? How about
|
|
\texttt{[0:[\textunderscore]...]}? Surprised?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:9}
|
|
Here are Cryptol's responses:\indModular\indEnum\indInfSeq
|
|
\begin{Verbatim}
|
|
[0, 1, 0, 1, 0, ...]
|
|
[0, 0, 0, 0, 0, ...]
|
|
\end{Verbatim}
|
|
The first example gets an element type of \texttt{[1]}, because of the
|
|
explicit use of the numeral \texttt{1}, while the second example's
|
|
element type is \texttt{[0]}. This is one case where \texttt{[k...]}
|
|
is subtly different from \texttt{[k, k+1...]}.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:arith:10}
|
|
What is the value of \texttt{[1 ..\ 10]}? Explain in terms of the above
|
|
discussion on modular arithmetic.\indModular
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:arith:10}
|
|
The expression \texttt{[1 ..\ 10]} is equivalent to \texttt{[1, (1+1) ..\ 10]},
|
|
and Cryptol knows that \texttt{10} requires at least 4 bits
|
|
to represent and uses the minimum implied by all the available
|
|
information. Hence we get: \texttt{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}.
|
|
You can use the \texttt{:t} command to see the type Cryptol infers for
|
|
this expression explicitly:
|
|
\begin{Verbatim}
|
|
Cryptol> :t [1 .. 10]
|
|
{a} (a >= 4, fin a) => [10][a]
|
|
\end{Verbatim}
|
|
Cryptol tells us that the sequence has precisely $10$ elements, and each
|
|
element is at least $4$ bits wide.
|
|
\todo[inline]{Reflect upon this ``at least'' a bit more.}
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Types}
|
|
% \label{sec:types}
|
|
\sectionWithAnswers{Types}{sec:types}
|
|
|
|
Cryptol's type system is one of its key features.\footnote{The Cryptol
|
|
type system is based on the traditional Hindley-Milner style,
|
|
extended with size types and arithmetic
|
|
predicates (for details, see~\cite{erkok-carlsson-wick-cryptolCoverification-09,
|
|
erkok-matthews-cryptolEqChecking-09, Hin97})} You have seen that
|
|
types can be used to specify the exact width of values, or shapes of
|
|
sequences using a rich yet concise notation. In some cases, it may
|
|
make sense to omit a type signature and let Cryptol {\em infer} the
|
|
type for you. At the interpreter, you can check what type Cryptol
|
|
inferred with the \texttt{:t} command.
|
|
|
|
\todo[inline]{More structured discussion of top and bottom types, \texttt{inf}
|
|
and \texttt{fin}, and the precise kinds of type constraints that are
|
|
possible. Go over index as well wrt type-related terms.}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Monomorphic types}\indMonomorphism
|
|
\label{sec:monomorphic-types}
|
|
|
|
A monomorphic type is one that represents a concrete value. Most of
|
|
the examples we have seen so far fall into this category. Below, we
|
|
review the basic Cryptol types that make up all the monomorphic values
|
|
in Cryptol.
|
|
|
|
\paragraph*{Bits}\indTheBitType\indTrue\indFalse There are precisely
|
|
two bit values in Cryptol: {\tt True} and {\tt
|
|
False}. The type itself is written {\tt Bit}. When we want to be
|
|
explicit, we can write it as follows: \texttt{(2 >= 3) :\ Bit}. However,
|
|
with type inference\indTypeInference writing the {\tt Bit} type
|
|
explicitly is almost never needed.
|
|
|
|
\paragraph*{Words}\indTheWordType\indTheBitType A word type is written
|
|
{\tt [}$n${\tt ]}, where $n$ is a fixed
|
|
non-negative constant. The constant can be as large (or small) as you
|
|
like. So, you can talk about 2-bit quantities {\tt [2]}, as well as
|
|
384-bit ones {\tt [384]}, or even odd sizes like 17 {\tt [17]},
|
|
depending on the needs of your application. When we want to be
|
|
explicit about the type of a value, we say {\tt 5:[8]}. If we do not
|
|
specify a size, Cryptol's type inference engine will pick the
|
|
appropriate value depending on the context.\indTypeInference
|
|
Recall from \autoref{sec:words2} that a word is, in fact, a
|
|
sequence of bits. Hence, an equivalent (but verbose) way to write the
|
|
type {\tt [17]} is {\tt [17]Bit}, which we would say in English as
|
|
``a sequence of length 17, whose elements are Bits.''
|
|
|
|
\paragraph*{Integers}\indTheIntegerType The type \texttt{Integer}
|
|
represents the unbounded mathematical integers. Arithmetic on this
|
|
type will not overflow.
|
|
|
|
\paragraph*{Modular integers} The type \texttt{Z n} represents
|
|
the subset of the integers from 0 to \texttt{n} (not including \texttt{n}).
|
|
Arithmetic on these types is done modulo \texttt{n}.
|
|
|
|
\paragraph*{Rationals}\indTheRationalType The type \texttt{Rational} represents
|
|
the subset of the real line that can be represented as a ratio of integers.
|
|
As with the integers, arithmetic on this type does not overflow.
|
|
|
|
\paragraph*{Tuples}\indTheTupleType A tuple is a heterogeneous
|
|
collection of arbitrary number of
|
|
elements. Just like we write a tuple value by enclosing it in
|
|
parentheses, we write the tuple type by enclosing the component types
|
|
in parentheses, separated by commas: \texttt{(3, 5, True) :\ ([8], [32],
|
|
Bit)}. Tuples' types follow the same structure: \texttt{(2, (False, 3),
|
|
5) :\ ([8], (Bit, [32]), [32])}. A tuple component can be any type:
|
|
a word, another tuple, sequence, record, etc. Again, type inference
|
|
makes writing tuple types hardly ever necessary.\indTypeInference
|
|
|
|
\paragraph*{Sequences}\indTheSequenceType A sequence is simply a
|
|
collection of homogeneous elements. If the element type is $t$,
|
|
then we write the type of a sequence of $n$ elements as \texttt{[}$n$\texttt{]}$t$.
|
|
Note that $t$ can be a sequence type itself. For
|
|
instance, the type {\tt [12][3][6]} reads as follows: A sequence of
|
|
12 elements, each of which is a sequence of 3 elements, each of which
|
|
is a 6-bit-wide word.
|
|
|
|
The type of an infinite sequence is written \texttt{[inf]}$t$, where $t$
|
|
is the type of the elements.\indInfSeq \indInf
|
|
|
|
\begin{Exercise}\label{ex:types:1}
|
|
What is the total number of bits in the type {\tt [12][3][6]}?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:types:1}
|
|
We have $12$ elements, each of which is a sequence of $3$ elements;
|
|
so we have $12*3=36$ elements total. Each element is a 6-bit word;
|
|
so the total number of bits is $36*6 = 216$.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:types:2}
|
|
How would you write the type of an infinite sequence where each
|
|
element itself is an infinite sequence of 32-bit words? What is the
|
|
total bit size of this type?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:types:2} {\tt [inf][inf][32]}. The size of
|
|
such a value would be infinite!
|
|
\end{Answer}
|
|
|
|
\paragraph{Records}\indTheRecordType
|
|
A record is a heterogeneous collection of arbitrary number of labeled
|
|
elements. In a sense, they generalize tuples by allowing the
|
|
programmer to give explicit names to fields. The type of a record is
|
|
written by enclosing it in braces, separated by commas:
|
|
\texttt{\{x :\ [32], y :\ [32]\}}. Records can be nested and can contain arbitrary
|
|
types of elements (records, sequences, functions, etc.).
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Polymorphic types}\indPolymorphism
|
|
\label{sec:polymorphic-types}
|
|
|
|
Our focus so far has been on monomorphic types---the types that
|
|
concrete Cryptol values (such as {\tt True}, {\tt 3}, or {\tt [1, 2]})
|
|
can have. If all we had were monomorphic types, however, Cryptol
|
|
would be a very verbose and boring language. Instead, we would like
|
|
to be able to talk about collections of values, values whose types are
|
|
instances of a given polymorphic type. This facility is especially
|
|
important when we define functions, a topic we will get to shortly. In
|
|
the mean time, we will look at some of the polymorphic primitive
|
|
functions Cryptol provides to get a feeling for Cryptol's polymorphic
|
|
type system.
|
|
|
|
\paragraph{The tale of {\ttfamily{\textbf tail}}}\indTail
|
|
Cryptol's built in function {\tt tail} allows us to drop the first
|
|
element from a sequence, returning the remainder:
|
|
\begin{Verbatim}
|
|
Cryptol> tail [1 .. 5]
|
|
[2, 3, 4, 5]
|
|
Cryptol> tail [(False, (1:[8])), (True, 12), (False, 3)]
|
|
[(True, 12), (False, 3)]
|
|
Cryptol> tail [ (1:[16])... ]
|
|
[2, 3, 4, 5, 6, ...]
|
|
\end{Verbatim}
|
|
What exactly is the type of {\tt tail}? If we look at the first
|
|
example, one can deduce that {\tt tail} must have the type:
|
|
\begin{Verbatim}
|
|
tail : [5][8] -> [4][8]
|
|
\end{Verbatim}
|
|
That is, it takes a sequence of length 5, containing 8-bit values, and
|
|
returns a sequence that has length 4, containing 8-bit values. (The
|
|
type {\tt a -> b} denotes a function that takes a value of type {\tt
|
|
a} and delivers a value of type {\tt b}.)
|
|
|
|
However, the other example uses of {\tt tail} above suggest that it
|
|
must have the following types, respectively:
|
|
\begin{Verbatim}
|
|
tail : [10][32] -> [9][32]
|
|
tail : [3](Bit, [8]) -> [2](Bit, [8])
|
|
tail : [inf][16] -> [inf][16]
|
|
\end{Verbatim}
|
|
|
|
As we have emphasized before, Cryptol is strongly typed, meaning that
|
|
every entity (whether a Cryptol primitive or a user-defined function)
|
|
must have a well-defined type. Clearly, the types we provided for
|
|
\texttt{tail} above are quite different from each other. In particular, the
|
|
first example uses numbers as the element type, while the second has
|
|
tuples. So, how can \texttt{tail} be assigned a type that will make it
|
|
work on all these inputs?
|
|
|
|
If you are familiar C++ templates or Java generics, you might think
|
|
that Cryptol has some sort of an overloading mechanism that allows one
|
|
to define functions that can work on multiple types. While templates
|
|
and generics do provide a mental model, the correspondence is not very
|
|
strong. In particular, we never write multiple definitions for the
|
|
same function in Cryptol, i.e., there is no ad-hoc
|
|
overloading. However, what Cryptol has is a much stronger notion:
|
|
polymorphism, as would be advocated by languages such as Haskell or
|
|
ML~\cite{ML,Has98}.\indPolymorphism\indOverloading
|
|
|
|
Here is the type of {\tt tail} in Cryptol:
|
|
\begin{Verbatim}
|
|
Cryptol> :t tail
|
|
tail : {n, a} [1 + n]a -> [n]a
|
|
\end{Verbatim}
|
|
This is quite a different type from what we have seen so far. In
|
|
particular, it is a polymorphic type, one that can work over multiple
|
|
concrete instantiations of it. Here's how we read this type in
|
|
Cryptol:
|
|
\begin{quote} \texttt{tail} is a polymorphic function, parameterized over
|
|
\texttt{n} and \texttt{a}. The input is a sequence that contains
|
|
\texttt{1 + n} elements. The elements can be of an arbitrary type
|
|
\texttt{a}; there is no restriction on their structure. The result
|
|
is a sequence that contains \texttt{n} elements, where the elements
|
|
themselves have the same type as those of the input.
|
|
\end{quote}
|
|
In the case for \texttt{tail}, the parameter \texttt{n} is a size-parameter
|
|
(since it describes the size of a sequence), while \texttt{a} is a
|
|
shape-parameter, since it describes the shape of elements. The
|
|
important thing to remember is that each use of \texttt{tail} must
|
|
instantiate the parameters \texttt{n} and \texttt{a} appropriately. Let's
|
|
see how the instantiations work for our running examples:
|
|
|
|
\todo[inline]{Talk about the scope of the type system's expressiveness and its
|
|
limitations. Perhaps call it a ``size-polymorphic type system'' here
|
|
more explicitly so that readers who are into dependent types are not
|
|
offended or disappointed.}
|
|
|
|
\begin{center}
|
|
%\begin{adjustbox}{width={\textwidth},keepaspectratio}
|
|
\begin{tabular}[h]{c||c|c|l}
|
|
{\tt [n+1]a -> [n]a} & {\tt n} & {\tt a} & Notes \\ \hline\hline
|
|
{\tt [5][8] -> [4][8]} & 4 & {\tt [8]} & {\tt 1+n = 5} $\Rightarrow$ {\tt n = 4} \\\hline
|
|
{\tt [10][32] -> [9][32]} & 9 & {\tt [32]} & {\tt 1+n = 10} $ \Rightarrow$ {\tt n = 9} \\\hline
|
|
{\tt [3](Bit, [8]) -> [2](Bit, [8])} & 2 & {\tt (Bit, [8])} & The type {\tt a} is now a tuple \\\hline
|
|
{\tt [inf][16] -> [inf][16]} & {\tt inf} & {\tt [16]} & {\tt 1+n = inf} $\Rightarrow$ {\tt n = inf}
|
|
\end{tabular}
|
|
%\end{adjustbox}
|
|
\end{center}
|
|
|
|
In the last instantiation, Cryptol knows that $\infty - 1 = \infty$,
|
|
allowing us to apply {\tt tail} on both finite and infinite
|
|
sequences. The crucial point is that an instantiation must be found
|
|
that satisfies the required match. It is informative to see what
|
|
happens if we apply {\tt tail} to an argument where an appropriate
|
|
instantiation can not be found:
|
|
\begin{Verbatim}
|
|
Cryptol> tail True
|
|
[error] at <interactive>:1:6--1:10:
|
|
Type mismatch:
|
|
Expected type: [1 + ?n`859]?a`860
|
|
Inferred type: Bit
|
|
where
|
|
?n`859 is type argument 'n' of 'tail' at <interactive>:1:1--1:5
|
|
?a`860 is type argument 'a' of 'tail' at <interactive>:1:1--1:5
|
|
\end{Verbatim}
|
|
Cryptol is telling us that it cannot match the types \texttt{Bit} and
|
|
the sequence \texttt{[1+n]a}, causing a type error statically at
|
|
compile time. (The funny notation of \texttt{?n`859} and
|
|
\texttt{?a`860} are due to how type instantiations proceed under the
|
|
hood. While they look funny at first, you soon get used to the
|
|
notation.)
|
|
|
|
We should emphasize that Cryptol polymorphism\indPolymorphism
|
|
uniformly applies to user-defined functions as well, as we shall see
|
|
in \autoref{sec:funcs}.
|
|
|
|
\begin{Exercise}\label{ex:poly:split}\indGroup
|
|
Use the \texttt{:t} command to find the type of \texttt{split}. For
|
|
each use case below, find out what the instantiations of its type
|
|
variables are, and justify why the instantiation works. Can you find
|
|
an instantiation in all these cases?
|
|
\begin{Verbatim}
|
|
split`{3} [1..9]
|
|
split`{3} [1..12]
|
|
split`{3} [1..10] : [3][2][8]
|
|
split`{3} [1..10]
|
|
\end{Verbatim}
|
|
Is there any way to make the last example work by giving a type signature?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:poly:split}\indGroup
|
|
Here is the type of \texttt{split}:
|
|
\begin{Verbatim}
|
|
Cryptol> :t split
|
|
split : {parts, each, a} (fin each) =>
|
|
[parts * each]a -> [parts][each]a
|
|
\end{Verbatim}
|
|
At every use case of \texttt{split} we must instantiate the parameters
|
|
\texttt{parts}, \texttt{each}, and \texttt{a}, so that the resulting
|
|
instantiation will match the use case. In the first example, we can
|
|
simply take: \texttt{parts = 3}, \texttt{each = 3}, and \texttt{a = [4]}. In
|
|
the second, we can take \texttt{parts=3}, \texttt{each=4}, and
|
|
\texttt{a=[4]}. The third expression does not type-check. Cryptol
|
|
tells us:
|
|
\begin{Verbatim}
|
|
Cryptol> split`{3} [1..10] : [3][2][8]
|
|
[error] at <interactive>:1:11--1:18:
|
|
Type mismatch:
|
|
Expected type: 6
|
|
Inferred type: 10
|
|
\end{Verbatim}
|
|
In this case, we are telling Cryptol that \texttt{parts = 3},
|
|
\texttt{each = 2}, and \texttt{a = [8]} by providing the explicit type
|
|
signature.\indSignature Using this information, Cryptol must ensure
|
|
that the argument matches the instantiation of the the polymorphic
|
|
type. The argument to \texttt{split} must have type \texttt{[parts *
|
|
each]a}; instantiating the type variables, this is \texttt{[3 *
|
|
2][8]}, or \texttt{[6][8]}. However, the given argument has length
|
|
\texttt{10}, which is not equal to \texttt{6}. It is not hard to see
|
|
that there is no instantiation to make this work, since \texttt{10} is
|
|
not divisible by \texttt{3}.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Predicates}
|
|
\label{sec:predicates}
|
|
|
|
\todo[inline]{Should we introduce a better predicates example?}
|
|
|
|
In the previous section we have seen how polymorphism is a powerful
|
|
tool in structuring programs. Cryptol takes the idea of polymorphism
|
|
on sizes one step further by allowing predicates on
|
|
sizes.\indPredicates To illustrate the notion, consider the type of
|
|
the Cryptol primitive {\tt take}\indTake:
|
|
\begin{Verbatim}
|
|
Cryptol> :t take
|
|
take : {front, back, a} (fin front) => [front + back]a -> [front]a
|
|
\end{Verbatim}
|
|
|
|
The type of {\tt take} says that it is parameterized over {\tt front}
|
|
and {\tt back}, {\tt front} must be a finite value,\indFin it takes a
|
|
sequence {\tt front + back} long, and returns a sequence {\tt front} long.
|
|
|
|
The impact of this predicate shows up when we try to take more than
|
|
what is available:
|
|
\begin{Verbatim}
|
|
Cryptol> take`{10} [1..5]
|
|
[error] at <interactive>:1:11--1:17:
|
|
Adding 10 will always exceed 5
|
|
\end{Verbatim}
|
|
Cryptol is telling us that it is unable to satisfy this instantiation
|
|
(since {\tt front} is 10 and the sequence has 5
|
|
elements).\indTake\indPredicates
|
|
|
|
In general, type predicates exclusively describe \textit{arithmetic
|
|
constraints on type variables}. Cryptol does not have a
|
|
general-purpose dependent type system, but a \emph{size-polymorphic
|
|
type system}. Often type variables' values are of finite size,
|
|
indicated with the constraint {\tt fin a}\indFin; otherwise no
|
|
constraint is mentioned, and the variables' values are unbounded,
|
|
possibly taking the value \texttt{inf}\indInf. Arithmetic
|
|
relations are arbitrary relations over all type variables, such as
|
|
{\tt 2*a+b >= c}. We shall see more examples as we work through
|
|
programs later on.
|
|
|
|
\begin{Exercise}\label{ex:preds:1}
|
|
Write a predicate that allows a word of size {\tt 128}, {\tt 192},
|
|
or {\tt 256}, but nothing else.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:preds:1}\indPredicates
|
|
Here is one way of writing this predicate, following the fact that
|
|
$128 = 2 * 64$, $192 = 3 * 64$, and $256 = 4 * 64$:
|
|
\begin{verbatim}
|
|
{k} (2 <= k, k <= 4) => [k*64]
|
|
\end{verbatim}
|
|
\todo[inline]{FIXME: The following example type signature is rejected by Cryptol, as subtraction is undefined when it underflows.}
|
|
Here is another way, more direct but somewhat less satisfying:
|
|
\begin{verbatim}
|
|
{k} ((k - 128) * (k - 192) * (k - 256) == 0) => [k]
|
|
\end{verbatim}
|
|
Note that Cryptol's type constraints do not include {\em or} predicates,
|
|
hence we cannot just list the possibilities in a list.
|
|
\end{Answer}
|
|
|
|
\note{Type inference in the presence of arithmetic predicates is an
|
|
undecidable problem~\cite{erkok-matthews-cryptolEqChecking-09}. This
|
|
implies that there is no algorithm to decide whether a given type is
|
|
inhabited, amongst other things. In practical terms, we might end
|
|
up writing programs with arbitrarily complicated predicates (e.g.,
|
|
this ``type contains all solutions to Fermat's last equation'' or
|
|
``this type contains all primes between two large numbers'') without
|
|
Cryptol being able to simplify them, or notice that there is no
|
|
instantiation that will ever work.\indUndecidable Here is a simple
|
|
example of such a type:}
|
|
\begin{Verbatim}
|
|
{k} (2 >= k, k >= 5) => [k]
|
|
\end{Verbatim}
|
|
While a moment of pondering suffices to conclude that there is no such
|
|
value in this particular case, there is no algorithm to decide this
|
|
problem in general.
|
|
|
|
That being said, Cryptol's type inference and type checking algorithms
|
|
are well-tuned to the use cases witnessed in the types necessary for
|
|
cryptographic algorithms. Moreover, Cryptol uses a powerful SMT
|
|
solver capable of reasoning about complex arithmetic theories within
|
|
these algorithms.
|
|
|
|
\todo[inline]{Precisely write up type system and type inference algorithm in
|
|
the Cryptol language guide or appendix. Reference which decision
|
|
procedures are actually used during type checking/inference.}
|
|
|
|
%%\subsection{Defaulting: A note on constants}
|
|
%% What is the type of {\tt 42}? We can ask Cryptol to find out:
|
|
%%\begin{Verbatim}
|
|
%% Cryptol> :t 42
|
|
%% 42 : [6]
|
|
%%\end{Verbatim}
|
|
%% However, {\tt 42} can in fact be of any size that is at least 6 bits
|
|
%% wide. So, why does Cryptol think it is just 6 bits? The reason is
|
|
%% because of defaulting.\indDefaulting The defaulting rule says that
|
|
%% Cryptol will pick the minimum size that will satisfy the
|
|
%% constraints, in the following two scenarios:
|
|
%%\begin{itemize}
|
|
%%\item At the top-level, i.e., when you type a number at the command
|
|
%% line,
|
|
%%\item In a nested expression, where the type variable does not
|
|
%% contribute to the overall type of the definition.
|
|
%%\end{itemize}
|
|
%% For the time being, let us simply focus on the first case: When we
|
|
%% type a number in the command line. Cryptol does this so that simple
|
|
%% arithmetic expressions at the top-level can produce the {\em
|
|
%% expected} values, instead of being overly polymorphic. You can
|
|
%% turn off this behavior by issuing the command {\tt :set
|
|
%% -d}:\indSettingDefaulting
|
|
%%\begin{Verbatim}
|
|
%% Cryptol> :set -d
|
|
%% Cryptol> :t 42
|
|
%% 42 : {a} (a >= 6) => [a]
|
|
%%\end{Verbatim}
|
|
%% Now, Cryptol is telling us {\tt 42} actually is a word that is at
|
|
%% least {\tt 6} bits wide. As a consequence, we now have more
|
|
%% polymorphic results:
|
|
%%\begin{Verbatim}
|
|
%% Cryptol> 4+1
|
|
%% <polymorphic value> : {a} (a >= 3) => [a]
|
|
%%\end{Verbatim}
|
|
%% When defaulting is off, even simple expressions like the one above
|
|
%% will produce polymorphic results, which would require the user to
|
|
%% be explicit about the types:
|
|
%%\begin{Verbatim}
|
|
%% Cryptol> 4+1 : [8]
|
|
%% 5
|
|
%%\end{Verbatim}
|
|
%% Some consider this style to be superior to the implicit defaulting,
|
|
%% as it forces the user to be explicit. However, the defaulting
|
|
%% behavior is enabled by default, since otherwise interactions with
|
|
%% the interpreter would be very painful. This is true especially in
|
|
%% the case of nested expressions in Cryptol programs, as we shall see
|
|
%% in \autoref{sec:pitfall:defaulting}.
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Why typed?}
|
|
\label{sec:why-typed}
|
|
|
|
There is a spectrum of type systems employed by programming languages,
|
|
all the way from completely untyped to fancier dependently typed
|
|
languages. There is no simple answer to the question, what type system
|
|
is the best? It depends on the application domain. We have found that
|
|
Cryptol's size-polymorphic type system is a good fit for programming
|
|
problems that arise in the domain of cryptography. The bit-precise
|
|
type system makes sure that we never pass an argument that is 32 bits
|
|
wide in a buffer that can only fit 16. The motto is: {\em Well typed
|
|
programs do not go wrong}.
|
|
|
|
In practical terms, this means that the type system catches most of
|
|
the common mistakes that programmers tend to make. Size-polymorphism
|
|
is a good fit for Cryptol, as it keeps track of the most important
|
|
invariant in our application domain: making sure the sizes of data can
|
|
be very precisely specified and the programs can be statically
|
|
guaranteed to respect these sizes.
|
|
|
|
Opponents of type systems typically argue that the type system gets in
|
|
the way.\footnote{Another complaint is that ``strong types are for
|
|
weak minds.'' We do not disagree here: Cryptol programmers want to
|
|
use the type system so we do not have to think as hard about writing
|
|
correct code as we would without strong types.} It is true that
|
|
the type system will reject some programs that makes perfect
|
|
sense. But what is more important is that the type system will reject
|
|
programs that will indeed go wrong at run-time. And the price you pay
|
|
to make sure your program type-checks is negligible, and the savings
|
|
due to type checking can be enormous.
|
|
|
|
The crucial question is not whether we want type systems, but rather
|
|
what type system is the best for a given particular application
|
|
domain. We have found that the size-polymorphic type system of Cryptol
|
|
provides the right balance for the domain of cryptography and
|
|
bit-precise programming problems it has been designed
|
|
for~\cite{lewis2003}.
|
|
|
|
%=====================================================================
|
|
% \section{Defining functions}
|
|
% \label{sec:funcs}
|
|
\sectionWithAnswers{Defining functions}{sec:funcs}
|
|
|
|
So far, we used Cryptol as a calculator: we typed in expressions and
|
|
it gave us answers. This is great for experimenting, and exploring
|
|
Cryptol itself. The next fundamental Cryptol idiom is the notion of a
|
|
function. You have already used built-in functions {\tt +}, {\tt
|
|
take}, etc.{\indPlus\indLg}Of course, users can define their own
|
|
functions as well. The recommended method is to define them in a file
|
|
and load it, as in the next exercises.
|
|
|
|
\note{Reviewing the contents of \autoref{sec:technicalities} might
|
|
help at this point. Especially the commands that will let you load
|
|
files ({\tt :l} and {\tt :r}) in Cryptol.\indCmdLoad\indCmdReload}
|
|
|
|
\begin{Exercise}\label{ex:fn:0}
|
|
Type the following definition into a file and save it. Then load it
|
|
in Cryptol and experiment.
|
|
\begin{code}
|
|
increment : [8] -> [8]
|
|
increment x = x+1
|
|
\end{code}
|
|
In particular, try the following invocations:
|
|
\begin{Verbatim}
|
|
increment 3
|
|
increment 255
|
|
increment 912
|
|
\end{Verbatim}
|
|
Do you expect the last call to type-check?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:fn:0}
|
|
Here are some example uses of {\tt increment}:
|
|
\begin{Verbatim}
|
|
Cryptol> increment 3
|
|
4
|
|
Cryptol> increment 255
|
|
0
|
|
Cryptol> increment 912
|
|
[error] at <interactive>:1:1--1:14:
|
|
Unsolvable constraint: 8 >= 10
|
|
\end{Verbatim}
|
|
Note how type inference rejects application when applied to an
|
|
argument of the wrong size: 912 is too big to fit into 8 bits.
|
|
\end{Answer}
|
|
|
|
\note{We do not have to parenthesize the argument to {\tt
|
|
increment}, as in {\tt increment(3)}. Function application is
|
|
simply juxtaposition in Cryptol. However, you can write the
|
|
parentheses if you want to, and you must use parentheses if you want
|
|
to pass a negative argument, e.g. \texttt{increment(-2)} (recall
|
|
\exerciseref{ex:arith:5}).}\indFunApp
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Definitions in the interpreter with \texttt{let}}
|
|
\label{sec:interpreter-let}
|
|
As an alternative to creating and loading files, the Cryptol
|
|
interpreter also supports simple definitions with \texttt{let}. Unlike
|
|
file-based definitions, \texttt{let}-definitions are not persistent:
|
|
They exist only until the same name is redefined or the interpreter
|
|
exits with \texttt{:q}.
|
|
\begin{code}
|
|
Cryptol> let r = {a = True, b = False}
|
|
Cryptol> r.a
|
|
True
|
|
\end{code}
|
|
Simple functions can be defined in the interpreter with \texttt{let},
|
|
with some restrictions: They must be entered on a single line, and
|
|
they cannot have a separate type signature. If we want a function to
|
|
have a more specific type than the inferred one, we must add type
|
|
annotations to variables or other parts of the body of the definition.
|
|
\begin{Exercise}\label{ex:fn:0b}
|
|
Enter the following definition into the Cryptol interpreter and check
|
|
its type with \texttt{:t}.
|
|
\begin{code}
|
|
let increment x = x+1
|
|
\end{code}
|
|
Modify the \texttt{let}-definition of \texttt{increment} so that it
|
|
will have type \texttt{[8] -> [8]}.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:fn:0b}
|
|
Any of the following definitions will have the desired type:
|
|
\begin{Verbatim}
|
|
Cryptol> let increment (x : [8]) = x + 1
|
|
Cryptol> let increment x = (x : [8]) + 1
|
|
Cryptol> let increment x = x + (1 : [8])
|
|
Cryptol> let increment x = x + 1 : [8]
|
|
Cryptol> :t increment
|
|
increment : [8] -> [8]
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Local names: {\ttfamily{\textbf where}} clauses}
|
|
\label{sec:local-names:-ttfam}
|
|
|
|
You can create local bindings in a {\tt where} clause\indWhere, to
|
|
increase readability and give names to common subexpressions.
|
|
|
|
\begin{Exercise}\label{ex:fn:1}
|
|
Define and experiment with the following function:
|
|
\begin{code}
|
|
twoPlusXY : ([8], [8]) -> [8]
|
|
twoPlusXY (x, y) = 2 + xy
|
|
where xy = x * y
|
|
\end{code}
|
|
What is the signature of the function telling us?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:fn:1}
|
|
The signature indicates that {\tt twoPlusXY} is a function that
|
|
takes two 8-bit words as a tuple, and returns an 8-bit word.
|
|
\end{Answer}
|
|
\note{When calling {\tt twoPlusXY}, you do need to parenthesize the
|
|
arguments. But this is because you are passing it a
|
|
tuple!\indFunApp The parentheses there are not for the application
|
|
but rather in construction of the argument tuple. Cryptol does not
|
|
automatically convert between tuples and curried application like in
|
|
some other programming languages (e.g., one cannot pass a pair of
|
|
type \texttt{(a, b)} to a function with type \texttt{a -> b -> c}).}
|
|
|
|
\begin{Exercise}\label{ex:fn:1.1}
|
|
Comment out the type signature of {\tt twoPlusXY} defined above, and
|
|
let Cryptol infer its type. What is the inferred type? Why?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:fn:1.1}
|
|
Here is the type Cryptol infers:
|
|
\begin{verbatim}
|
|
Cryptol> :t twoPlusXY
|
|
twoPlusXY : {a} (a >= 2, fin a) => ([a],[a]) -> [a]
|
|
\end{verbatim}
|
|
That is, our function will actually work over arbitrary (finite) sized
|
|
words, as long as they are at least 2 bits wide. The 2-bit requirement
|
|
comes from the constant 2, which requires at least 2 bits to
|
|
represent.
|
|
\end{Answer}
|
|
|
|
\todo[inline]{The Cmp class has not been introduced yet. At least, add a forward reference to the ``Type classes'' section.}
|
|
\begin{Exercise}\label{ex:fn:2}
|
|
Define a function with the following signature:
|
|
\begin{Verbatim}
|
|
minMax4 : {a} (Cmp a) => [4]a -> (a, a)
|
|
\end{Verbatim}
|
|
such that the first element of the result is the minimum and the
|
|
second element is the maximum of the given four elements. What happens
|
|
when you try:
|
|
\begin{Verbatim}
|
|
minMax4 [1 .. 4]
|
|
minMax4 [1 .. 5]
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\noindent Why do we need the {\tt \Verb+(Cmp a)+} constraint?\indFin
|
|
\begin{Answer}\ansref{ex:fn:2}
|
|
Here is one way of defining this function:\indMin\indMax
|
|
\begin{code}
|
|
minMax4 : {a} (Cmp a) => [4]a -> (a, a)
|
|
minMax4 [a, b, c, d] = (e, f)
|
|
where e = min a (min b (min c d))
|
|
f = max a (max b (max c d))
|
|
\end{code}
|
|
Note that ill-typed arguments will be caught at compile time! So, the
|
|
second invocation with the 5 element sequence will fail to type-check.
|
|
The {\tt Cmp a} constraint arises from the types of {\tt min} and {\tt
|
|
max} primitives:\indMin\indMax
|
|
\begin{Verbatim}
|
|
min, max : {a} (Cmp a) => a -> a -> a
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:fn:3}
|
|
Define a function {\tt butLast} that returns all the elements of a
|
|
given non-empty sequence, except for the last. How can you make
|
|
sure that {\tt butLast} can never be called with an empty sequence?
|
|
\lhint{You might find the Cryptol primitive functions {\tt reverse}
|
|
and {\tt tail} useful.}\indReverse\indTail
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:fn:3}
|
|
Using {\tt reverse} and {\tt tail}, {\tt butLast} is easy to
|
|
define:\indReverse\indTail
|
|
\begin{code}
|
|
butLast : {n, t} (fin n) => [n+1]t -> [n]t
|
|
butLast xs = reverse (tail (reverse xs))
|
|
\end{code}
|
|
Here is another way to define {\tt butLast}:
|
|
\begin{code}
|
|
butLast' : {count, x} (fin count) => [count+1]x -> [count]x
|
|
butLast' xs = take`{count} xs
|
|
\end{code}
|
|
The type signature sets {\tt count} to the desired width of the
|
|
output, which is one shorter than the width of the input:\indSignature
|
|
\begin{Verbatim}
|
|
Cryptol> butLast []
|
|
|
|
[error] at <interactive>:1:1--1:11:
|
|
Unsolved constraint:
|
|
0 >= 1
|
|
arising from
|
|
matching types
|
|
at <interactive>:1:1--1:11
|
|
\end{Verbatim}
|
|
At first the error message might be confusing. What Cryptol is telling
|
|
us that it deduced {\tt count+1} must be {\tt 1}, which makes {\tt
|
|
count} have value {\tt 0}. But the {\tt count+1} we gave it was 0,
|
|
which is not greater than or equal to 1.
|
|
|
|
Finally, note that {\tt butLast} requires a finite sequence as input,
|
|
for obvious reasons, and hence the {\tt fin n} constraint.
|
|
\end{Answer}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{\texorpdfstring{\lamexs}{Lambda-expressions}}\label{sec:lamex}
|
|
|
|
One particular use case of a {\tt where} clause\indWhere is to
|
|
introduce a helper function. If the function is simple enough, though,
|
|
it may not be worth giving it a name. A \lamex fits the bill in these
|
|
cases, where you can introduce an unnamed function as an
|
|
expression. The syntax differs from ordinary definitions in two minor
|
|
details: instead of the name we use the backslash or ``whack''
|
|
character, `{\tt \Verb|\|}', and the equals sign is replaced by an
|
|
arrow `{\tt ->}'. (Since these functions do not have explicit names,
|
|
they are sometimes referred to as ``anonymous functions'' as well. We
|
|
prefer the term \lamex, following the usual functional programming
|
|
terminology~\cite{Has98}.)
|
|
|
|
\todo[inline]{See
|
|
\href{https://www.galois.com/cryptol/ticket/89}{ticket \#89}. This
|
|
is also about our currently-weak REPL.}
|
|
|
|
Below is an example of a \lamex, allowing us to write functions inline:
|
|
\begin{Verbatim}
|
|
Cryptol> f 8 where f x = x+1
|
|
9
|
|
Cryptol> (\x -> x+1) 8
|
|
9
|
|
\end{Verbatim}
|
|
\lamexs are especially handy when you need to write small functions at
|
|
the command line while interacting with the interpreter.
|
|
|
|
\todo[inline]{Is the following note exclusively from Cryptol v1? Should there
|
|
by a ticket? Removing for now.}
|
|
|
|
% \note{The former example shows that in addition to the
|
|
% indentation-based layout, Cryptol supports the more traditional
|
|
% curly-braces and semicolon-based block structure. At the command
|
|
% line is the primary (only?) place this option should be used.}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Using {\tt zero} in functions}
|
|
\label{sec:using-tt-zero}
|
|
|
|
The constant {\tt zero}\indZero comes in very handy in Cryptol
|
|
whenever we need a polymorphic shape that consists of all {\tt False}
|
|
bits. The following two exercises utilize {\tt zero} to define the
|
|
functions {\tt all}\indAll and {\tt any}\indAny which, later in this
|
|
book, you will find are very helpful functions for producing boolean
|
|
values from a sequence.
|
|
|
|
\begin{Exercise}\label{ex:zero:1}
|
|
Write a function {\tt all} with the following signature:\indAll
|
|
\begin{code}
|
|
all : {n, a} (fin n) => (a -> Bit) -> [n]a -> Bit
|
|
\end{code}
|
|
such that {\tt all f xs} returns {\tt True} if all the elements in the
|
|
sequence {\tt xs} yield {\tt True} for the function {\tt f}.
|
|
\lhint{Use a complemented {\tt zero}.} You should see:
|
|
\begin{Verbatim}
|
|
Cryptol> all eqTen [10, 10, 10, 10] where eqTen x = x == 10
|
|
True
|
|
Cryptol> all eqTen [10, 10, 10, 5] where eqTen x = x == 10
|
|
False
|
|
\end{Verbatim}
|
|
(The {\tt where} clause introduces a local definition that is in scope
|
|
in the current expression. We have seen the details in
|
|
\autoref{sec:funcs}.\indWhere) What is the value of {\tt all f []}
|
|
for an arbitrary function {\tt f}? Is this reasonable?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:zero:1}
|
|
\begin{code}
|
|
all f xs = [ f x | x <- xs ] == ~zero
|
|
\end{code}
|
|
Note how we apply {\tt f} to each element in the sequence and check
|
|
that the result consists of all {\tt True}s, by using a complemented
|
|
{\tt zero}.\indZero\indAll If we pass {\tt any} an empty sequence,
|
|
then we will always get {\tt False}:
|
|
\begin{Verbatim}
|
|
Cryptol> any eqTen [] where eqTen x = x == 10
|
|
False
|
|
\end{Verbatim}
|
|
This is intuitively the correct behavior as well. The predicate is
|
|
satisfied by {\em none} of the elements in the sequence, but {\tt any}
|
|
requires at least one.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:zero:2}
|
|
Write a function {\tt any} with the following signature:\indAny
|
|
\begin{code}
|
|
any : {n, a} (fin n) => (a -> Bit) -> [n]a -> Bit
|
|
\end{code}
|
|
such that {\tt any f xs} returns {\tt True} if any the elements in the
|
|
sequence {\tt xs} yield {\tt True} for the function {\tt f}. What is
|
|
the value of {\tt any f []}? Is this reasonable?
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:zero:2}
|
|
\begin{code}
|
|
any f xs = [ f x | x <- xs ] != zero
|
|
\end{code}
|
|
This time all we need to make sure is that the result is not {\tt
|
|
zero}, i.e., at least one of elements yielded {\tt
|
|
True}.\indZero\indTrue\indAny If we pass {\tt all} an empty
|
|
sequence, then we will always get {\tt False}:
|
|
\begin{Verbatim}
|
|
Cryptol> any eqTen [] where eqTen x = x == 10
|
|
False
|
|
\end{Verbatim}
|
|
Again, this is the correct response since there are no elements in an
|
|
empty sequence that can satisfy the predicate.
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Recursion and recurrences}
|
|
% \label{sec:recandrec}
|
|
\sectionWithAnswers{Recursion and recurrences}{sec:recandrec}
|
|
|
|
\todo[inline]{This section represents a big opportunity to emphasize sequence
|
|
comprehensions, motivate comprehensions, and help readers think that
|
|
way.}
|
|
|
|
\todo[inline]{This section is weak on recurrances. What is the \emph{real}
|
|
impact of a functional vs. recurrance style to the use of Cryptol?
|
|
Does such a style choice only impact type checking or inference, or
|
|
does it have implications on execution and reasoning (wrt
|
|
performance, overhead, soundness, and completeness)?}
|
|
|
|
Cryptol allows both recursive function and value definitions. A
|
|
recursive function is one that calls itself in its definition. Cryptol
|
|
also allows the more general form of mutual recursion, where multiple
|
|
functions can call each other in a cyclic
|
|
fashion.\indRecurrence\indRecursion
|
|
|
|
\todo[inline]{Are there any standard limitations witnessed in other systems
|
|
that are inherent in Cryptol as well that should be mentioned?
|
|
E.g., how does the typing infrastructure handle missing fixpoints?
|
|
Chains of type synonyms? Funny interactions with the module system?
|
|
Remind the reader about forward-referencing types. }
|
|
|
|
\begin{Exercise}\label{ex:recfun:1}
|
|
Define two functions {\tt isOdd} and {\tt isEven} that each take
|
|
a finite arbitrary sized word and returns a {\tt Bit}. The functions
|
|
should be mutually recursive. What extra predicates do you have to
|
|
put on the size?\indPredicates
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:1}
|
|
\begin{code}
|
|
isOdd, isEven : {n} (fin n, n >= 1) => [n] -> Bit
|
|
isOdd x = if x == 0 then False else isEven (x - 1)
|
|
isEven x = if x == 0 then True else isOdd (x - 1)
|
|
\end{code}
|
|
The extra predicate we need to add is {\tt n >=
|
|
1}.\indFin\indPredicates\indEq\indMinus This constraint comes from
|
|
the subtraction with 1, which requires at least 1 bit to represent.
|
|
\end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:recfun:1:5}
|
|
While defining {\tt isOdd} and {\tt isEven} mutually recursively
|
|
demonstrates the concept of recursion, it is not the best way of
|
|
coding these two functions in Cryptol. Can you implement them using
|
|
a constant time operation? \lhint{What is the least significant bit
|
|
of an even number? How about an odd one?}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:1:5}
|
|
A number is even if its least least significant bit is {\tt False},
|
|
and odd otherwise. Hence, we can define these functions as:
|
|
\begin{code}
|
|
isOdd', isEven' : {n} (fin n, n >= 1) => [n] -> Bit
|
|
isOdd' x = x ! zero
|
|
isEven' x = ~(x ! zero)
|
|
\end{code}
|
|
Note the use of {\tt zero} which permits Cryptol to choose the width
|
|
of the \texttt{0} constant appropriately.
|
|
\end{Answer}
|
|
|
|
\paragraph*{Recurrences} While Cryptol does support recursion, the
|
|
explicit recursive function style is typically discouraged: Arbitrary
|
|
recursion is hard to compile down to hardware.\indRecurrence A much
|
|
better notion is that of {\em recurrences}. A recurrence is a way of
|
|
cyclically defining a value, typically a stream.\indStream It turns
|
|
out that most recursive functions can be written in a recurrence style
|
|
as well, something that might first come as a surprise. In particular,
|
|
most recursive definitions arise from recurrence equations in
|
|
cryptographic and data flow style programs, and Cryptol's
|
|
comprehensions can succinctly represent these computations.\indComp
|
|
|
|
\todo[inline]{Justify/explain the following exercise's purpose and location.
|
|
Show the solution using recursion, either before or after, and show
|
|
how to convert from the recursive solution to the recurrance-based
|
|
one. Show the limitations of the recursive version.}
|
|
|
|
\begin{Exercise}\label{ex:recfun:2}
|
|
In this exercise, we will define a function to compute the maximum
|
|
element in a given sequence of numbers. Define the following
|
|
function and load it into Cryptol:\indRIndex\indRecurrence\indMax
|
|
\begin{code}
|
|
maxSeq xs = ys ! 0
|
|
where ys = [0] # [ max x y | x <- xs
|
|
| y <- ys
|
|
]
|
|
\end{code}
|
|
What is the type of {\tt maxSeq}? Try out the following calls:
|
|
\begin{Verbatim}
|
|
maxSeq []
|
|
maxSeq [1 .. 10]
|
|
maxSeq ([10, 9 .. 1] # [1 .. 10])
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:2}
|
|
The type of {\tt maxSeq} is:
|
|
\begin{Verbatim}
|
|
maxSeq : {a, b} (fin a, fin b) => [a][b] -> [b]
|
|
\end{Verbatim}
|
|
It takes a sequence of words and returns a word of the same size. The
|
|
suggested expressions produce {\tt 0}, {\tt 10}, and {\tt 10},
|
|
respectively.
|
|
\end{Answer}
|
|
|
|
\paragraph*{Patterns of recurrence} The definition pattern for {\tt ys}
|
|
in the definition of {\tt maxSeq} above is very common in Cryptol, and
|
|
it is well worth understanding it clearly.\indRecurrence The basic
|
|
idea is to create a sequence of running results, for each prefix of
|
|
the input.
|
|
|
|
\begin{Exercise}\label{ex:recfun:3}
|
|
Define a variant of {\tt maxSeq} (let us call it {\tt maxSeq'})
|
|
which returns the sequence {\tt ys}, instead of its last element.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:3}
|
|
We can simply drop the selection of the last element ({\tt ! 0}),
|
|
and write {\tt maxSeq'} as follows:\indRIndex
|
|
\begin{code}
|
|
maxSeq' : {a, b} (fin a,fin b) => [a][b] -> [1 + a][b]
|
|
maxSeq' xs = ys
|
|
where ys = [0] # [ max x y | x <- xs
|
|
| y <- ys
|
|
]
|
|
\end{code}
|
|
\end{Answer}
|
|
|
|
\paragraph*{Running results} It is very instructive to look at the
|
|
results returned by {\tt maxSeq'} that you have just defined in
|
|
\exerciseref{ex:recfun:3}:
|
|
\begin{Verbatim}
|
|
Cryptol> maxSeq' []
|
|
[0]
|
|
Cryptol> maxSeq' [1 .. 10]
|
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
Cryptol> maxSeq' [10, 9 .. 1]
|
|
[0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
|
|
Cryptol> maxSeq' [1, 3, 2, 4, 3, 5, 4, 7, 6, 8, 5]
|
|
[0, 1, 3, 3, 4, 4, 5, 5, 7, 7, 8, 8]
|
|
\end{Verbatim}
|
|
We clearly see the running results as they accumulate in {\tt ys}. For
|
|
the empty sequence, it only has {\tt [0]} in it. For the monotonically
|
|
increasing sequence {\tt \Verb+[1 .. 10]+}, the maximum value keeps
|
|
changing at each point, as each new element of {\tt xs} is larger than
|
|
the previous running result. When we try the sequence that always goes
|
|
down ({\tt [10, 9 .. 1]}), we find that the running maximum never
|
|
changes after the first. The mixed input in the last call clearly
|
|
demonstrates how the execution proceeds, the running maximum changing
|
|
depending on the next element of {\tt xs} and the running maximum so
|
|
far. In the {\tt maxSeq} function of \exerciseref{ex:recfun:2}, we
|
|
simply project out the last element of this sequence, obtaining the
|
|
maximum of all elements in the given sequence.
|
|
|
|
\paragraph*{Folds}\label{par:fold}\indFold The pattern of recurrence
|
|
employed in {\tt maxSeq} is an instance of what is known as a {\em
|
|
fold}~\cite{Bir98}. Expressed in Cryptol terms, it looks as
|
|
follows:
|
|
\begin{Verbatim}
|
|
ys = [i] # [ f (x, y) | x <- xs
|
|
| y <- ys
|
|
]
|
|
\end{Verbatim}
|
|
where {\tt xs} is some input sequence, {\tt i} is the result
|
|
corresponding to the empty sequence, and {\tt f} is a transformer to
|
|
compute the next element, using the previous result and the next
|
|
input. This pattern can be viewed as generating a sequence of running
|
|
values, accumulating them in {\tt ys}. To illustrate, if {\tt xs} is a
|
|
sequence containing the elements {\tt [$x_1$, $x_2$, $x_3$ .. $x_n$]},
|
|
then successive elements of {\tt ys} will be:
|
|
\begin{Verbatim}[commandchars=\\\{\}, codes={\catcode`$=3\catcode`^=7\catcode`_=8}]
|
|
$y_0$ = i
|
|
$y_1$ = f($x_1$, i)
|
|
$y_2$ = f($x_2$, $y_1$)
|
|
$y_3$ = f($x_3$, $y_2$)
|
|
...
|
|
$y_n$ = f($x_n$, $y_{n-1}$)
|
|
\end{Verbatim}
|
|
Note how each new element of {\tt ys} is computed by using the
|
|
previous element and the next element of the input. The value {\tt i}
|
|
provides the seed. Consequently, {\tt ys} will have one more element
|
|
than {\tt xs} does.
|
|
|
|
\paragraph*{While loops} An important use case of the above pattern is
|
|
when we are interested in the final value of the accumulating values,
|
|
as in the definition of {\tt maxSeq}.\indRIndex\indWhileLoop When used
|
|
in this fashion, the execution is reminiscent of a simple while loop
|
|
that you might be familiar with from other languages, such as C:
|
|
\begin{Verbatim}[commandchars=\\\{\}, codes={\catcode`$=3\catcode`^=7\catcode`_=8}]
|
|
-- C-like Pseudo-code!
|
|
y = i; // running value, start with i
|
|
idx = 0; // walk through the xs "array" using idx
|
|
while(idx < length (xs)) \{
|
|
y = f (xs[idx], y); // compute next elt using the previous
|
|
++idx;
|
|
\}
|
|
return y;
|
|
\end{Verbatim}
|
|
\note{If the while-loop analogy does not help you, feel free to ignore
|
|
it. It is not essential. The moral of the story is this: if you feel
|
|
like you need to write a while-loop in Cryptol to compute a value
|
|
dependent upon the values in a datatype, you probably want to use a
|
|
fold-like recurrence instead.}
|
|
|
|
\begin{Exercise}\label{ex:recfun:4}
|
|
Define a function that sums up a given sequence of elements. The
|
|
type of the function should be:
|
|
\begin{Verbatim}
|
|
sumAll : {n, a} (fin n, fin a) => [n][a] -> [a]
|
|
\end{Verbatim}
|
|
\lhint{Use the folding pattern to create a sequence containing the
|
|
partial running sums. What is the last element of this sequence?}
|
|
Try it out on the following examples:
|
|
\begin{Verbatim}
|
|
sumAll []
|
|
sumAll [1]
|
|
sumAll [1, 2]
|
|
sumAll [1, 2, 3]
|
|
sumAll [1, 2, 3, 4]
|
|
sumAll [1, 2, 3, 4, 5]
|
|
sumAll [1 .. 100]
|
|
\end{Verbatim}
|
|
Be mindful that if you do not specify the width of the result that you
|
|
may get unexpected answers.
|
|
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:4}
|
|
Here is one answer. Note that in this solution the width of the
|
|
answer is specified in terms of the width of the elements, so is
|
|
likely to overflow. You can prevent the overflow by explicitly
|
|
specifying the width of the output.
|
|
\begin{code}
|
|
sumAll : {n, a} (fin n, fin a) => [n][a] -> [a]
|
|
sumAll xs = ys ! 0
|
|
where ys = [0] # [ x+y | x <- xs
|
|
| y <- ys
|
|
]
|
|
\end{code}
|
|
\todo[inline]{Insert the recursive solution and a transformation to the
|
|
recurrance-based solution.}
|
|
\todo[inline]{Show how rich the type of \texttt{sumAll} could be with a full
|
|
dependent type system vs. what we have at our disposal.}
|
|
In this code, the sequence {\tt ys} contains the partial running sums.
|
|
This is precisely the same pattern we have seen in
|
|
Example~\ref{ex:recfun:3}. The output for the example calls are:
|
|
\begin{Verbatim}
|
|
CrashCourse> sumAll []
|
|
0
|
|
CrashCourse> sumAll [1]
|
|
1
|
|
CrashCourse> sumAll [1, 2]
|
|
3
|
|
CrashCourse> sumAll [1, 2, 3]
|
|
2
|
|
CrashCourse> sumAll [1, 2, 3, 4]
|
|
2
|
|
CrashCourse> sumAll [1, 2, 3, 4, 5]
|
|
7
|
|
CrashCourse> sumAll [1 .. 100]
|
|
58
|
|
\end{Verbatim}
|
|
If we do not explicitly tell Cryptol how wide the result is, then it
|
|
will pick the width of the input elements, which will cause overflow
|
|
and be subject to modular arithmetic as usual. Experiment with
|
|
different signatures for {\tt sumAll}, to avoid the overflow
|
|
automatically, to get the answers:
|
|
\begin{Verbatim}
|
|
0
|
|
1
|
|
3
|
|
6
|
|
10
|
|
15
|
|
5050
|
|
\end{Verbatim}
|
|
\indModular\indOverflow \end{Answer}
|
|
|
|
\begin{Exercise}\label{ex:recfun:4:1}
|
|
Define a function {\tt elem} with the following signature:\indElem
|
|
\begin{code}
|
|
elem : {n, t} (fin n, Eq t) => (t, [n]t) -> Bit
|
|
\end{code}
|
|
such that {\tt elem (x, xs)} returns {\tt True} if {\tt x} appears in
|
|
{\tt xs}, and {\tt False} otherwise.\footnote{Note: this function
|
|
is already present in the Cryptol prelude.}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:4:1}
|
|
Using a fold, it is easy to write {\tt elem}:
|
|
\begin{code}
|
|
elem (x, xs) = matches ! 0
|
|
where matches = [False] # [ m || (x == e) | e <- xs
|
|
| m <- matches
|
|
]
|
|
\end{code}
|
|
Note how we or ({\tt ||})\indOr the previous result {\tt m} with the
|
|
current match, accumulating the result as we walk over the
|
|
sequence. Starting with {\tt False} ensures that if none of the
|
|
matches succeed we will end up returning {\tt False}. We have:
|
|
\begin{Verbatim}
|
|
Cryptol> elem (2, [1..10])
|
|
True
|
|
Cryptol> elem (0, [1..10])
|
|
False
|
|
Cryptol> elem (10, [])
|
|
False
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
\paragraph*{Generalized folds} The use of fold we have seen above is
|
|
the simplest use case for recurrences in Cryptol.\indFold\indComp It
|
|
is very common to see Cryptol programs employing some variant of this
|
|
idea for most of their computations.
|
|
|
|
\todo[inline]{Again, show the recursion-based version of \texttt{fibs}
|
|
and its limitations.}
|
|
|
|
\begin{Exercise}\label{ex:recfun:5}
|
|
Define the sequence of Fibonacci numbers {\tt fibs}, so that {\tt
|
|
fibs @ n} is the $n^{\mbox{th}}$ Fibonacci
|
|
number~\cite{wiki:fibonacci}.\glosFibonacci You can assume 32 bits
|
|
is sufficient for representing these fast growing
|
|
numbers. \lhint{Use a recurrence where the seed consists of two
|
|
elements.}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:recfun:5}
|
|
\begin{code}
|
|
fibs : [inf][32]
|
|
fibs = [0, 1] # [ x+y | x <- fibs
|
|
| y <- drop`{1} fibs
|
|
]
|
|
\end{code}
|
|
In this case we use the sequence {\tt [0, 1]} as the seed, and both
|
|
branches recursively refer to the defined value {\tt fibs}. In the
|
|
second branch, we {\tt drop} the first element to skip over the first
|
|
element of the sequence, effectively pairing the previous two elements
|
|
at each step. The $n$th fibonacci number is obtained by the
|
|
expression {\tt fibs @ n}:\indDrop
|
|
\begin{Verbatim}
|
|
Cryptol> fibs @ 3
|
|
2
|
|
Cryptol> fibs @ 4
|
|
3
|
|
Cryptol> take`{10} fibs
|
|
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
|
\end{Verbatim}
|
|
Note that {\tt fibs} is an infinite stream of 32 bit numbers, so it
|
|
will eventually be subject to wrap-around due to modular
|
|
arithmetic.\indModular
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Stream equations}
|
|
% \label{sec:streameq}
|
|
\sectionWithAnswers{Stream equations}{sec:streameq}
|
|
|
|
Most cryptographic algorithms are described in terms of operations on
|
|
bit-streams.\indStreamEquation A common way of depicting operations on
|
|
bit-streams is using a {\it stream equation,} as shown in
|
|
Figure~\ref{fig:streamDiagram}:
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=3.5in]{crashCourse/streamDiagram.pdf}
|
|
\caption{Equation for producing a stream of {\tt as}}
|
|
\label{fig:streamDiagram}
|
|
\end{figure}
|
|
|
|
In this diagram the stream is seeded with four initial values ({\tt
|
|
3F, E2, 65, CA}). The subsequent elements ({\tt new}) are appended
|
|
to the stream, and are computed by xor-ing the current stream element
|
|
with two additional elements extracted from further into the stream.
|
|
The output from the stream is a sequence of values, known as $a$s.
|
|
|
|
The Cryptol code corresponding to this stream equation is:
|
|
\begin{code}
|
|
as = [0x3F, 0xE2, 0x65, 0xCA] # new
|
|
where
|
|
new = [ a ^ b ^ c | a <- as
|
|
| b <- drop`{1} as
|
|
| c <- drop`{3} as ]
|
|
\end{code}
|
|
|
|
% \vfill
|
|
% \eject
|
|
\todo[inline]{Make sure pagination looks good, particularly for figures.}
|
|
|
|
\begin{Exercise}\label{ex:streamEq}
|
|
Write the Cryptol code corresponding to the stream equation in
|
|
Figure~\ref{fig:streamExercise}:
|
|
\end{Exercise}
|
|
\begin{figure}[htbp]
|
|
\centering
|
|
\includegraphics[width=4in]{crashCourse/streamExercise}
|
|
\caption{Equation for producing a stream of {\tt as} from an initial
|
|
seed and an input stream.}
|
|
\label{fig:streamExercise}
|
|
\end{figure}
|
|
|
|
\todo[inline]{Update diagram so that the output is called \texttt{xs}
|
|
to match the solution and we avoid getting an error from Cryptol
|
|
about redeclaration of \texttt{as}.}
|
|
|
|
\begin{Answer}\ansref{ex:streamEq}
|
|
\begin{code}
|
|
xs input = as where
|
|
as = [0x89, 0xAB, 0xCD, 0xEF] # new
|
|
new = [ a ^ b ^ c | a <- as
|
|
| b <- drop`{2} as
|
|
| c <- input ]
|
|
\end{code}
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
% \section{Type synonyms}
|
|
% \label{sec:tsyn}
|
|
\sectionWithAnswers{Type synonyms}{sec:tsyn}\indTypSynonym
|
|
|
|
\todo[inline]{Motivate type synonyms better; NQueens with nice
|
|
synonyms is a good example.}
|
|
|
|
\todo[inline]{Should we insert a section on currying-style functions
|
|
vs. tuples here?}
|
|
|
|
Types in Cryptol can become fairly complicated, especially in the
|
|
presence of records. Even for simple types, meaningful names should
|
|
be used for readability and documentation. Type synonyms allow users
|
|
to give names to arbitrary types. In this sense, they are akin to
|
|
{\tt typedef} declarations in C~\cite{TheCProgrammingLanguage}.
|
|
However, Cryptol's type synonyms are significantly more powerful than
|
|
C's {\tt typedef}s, since they can be parameterized by other types,
|
|
much like in Haskell~\cite{Has98}.
|
|
|
|
\todo[inline]{Add a discussion of N-queens or AES or something more compelling
|
|
to show off type synonyms.}
|
|
|
|
Here are some simple type synonym definitions:
|
|
\begin{code}
|
|
type Word8 = [8]
|
|
type CheckedWord = (Word8, Bit)
|
|
type Point a = {x : [a], y : [a]}
|
|
\end{code}
|
|
|
|
\todo[inline]{2.0: Rewrite this paragraph and much of this section.}
|
|
|
|
Type synonyms are either unparameterized (as in {\tt Word8} and {\tt
|
|
CheckedWord}, or parameterized with other types (as in {\tt Point}).
|
|
Synonyms may depend upon other synonyms, as in the {\tt CheckedWord}
|
|
example. Once the synonym is given, it acts as an additional name for
|
|
the underlying type, making it much easier to read and
|
|
maintain.
|
|
|
|
For instance, we can write the function that returns the x-coordinate
|
|
of a point as follows:
|
|
\begin{code}
|
|
xCoord : {a} Point a -> [a]
|
|
xCoord p = p.x
|
|
\end{code}
|
|
|
|
Type synonyms look like distinct types when they are printed in the
|
|
output of the \texttt{:t} and \texttt{:browse} commands. However,
|
|
declaring a type synonym does not actually introduce a new
|
|
\emph{type}; it merely introduces a new \emph{name} for an existing
|
|
type. When Cryptol's type checker compares types, it expands all type
|
|
synonyms first. So as far as Cryptol is concerned, \texttt{Word8} and
|
|
\texttt{[8]} are the \emph{same} type. Cryptol preserves type synonyms
|
|
in displayed types as a convenience to the user.
|
|
|
|
For example, consider the following declarations:
|
|
%% not "code" to avoid conflicting with previous Word8
|
|
\begin{Verbatim}
|
|
type Word8 = [8]
|
|
type Word8' = [8]
|
|
type B = Word8
|
|
type A = B
|
|
type WordPair = (Word8, Word8')
|
|
type WordPair' = (Word8', Word8)
|
|
|
|
foo : Word8 -> Bit
|
|
foo x = True
|
|
|
|
bar : Word8' -> Bit
|
|
bar x = foo x
|
|
\end{Verbatim}
|
|
Within this type context, six different type \emph{names} are
|
|
declared, but there are not six distinct \emph{types}. The first four
|
|
(\texttt{Word8}, \texttt{Word8'}, \texttt{B}, and \texttt{A}) are all
|
|
interchangeable abbreviations for \texttt{[8]}. The last two are
|
|
synonymous and interchangeable with the pair type \texttt{([8], [8])}.
|
|
Likewise, the function types of \texttt{foo} and \texttt{bar} are
|
|
identical; thus \texttt{bar} can call \texttt{foo}.
|
|
|
|
\begin{Exercise}\label{ex:tsyn:1}
|
|
Define a type synonym for 3-dimensional points and write a function
|
|
to determine if the point lies on any of the 3 axes.
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:tsyn:1}
|
|
A point is on the $a^{\text{th}}$ axis if its non-$a^{\text{th}}$
|
|
components are $0$. Hence we have:
|
|
\begin{code}
|
|
type Point3D a = {x : [a], y : [a], z : [a]}
|
|
|
|
onAnAxis : {a} (fin a) => Point3D a -> Bit
|
|
onAnAxis p = onX || onY || onZ
|
|
where onX = (p.y == 0) && (p.z == 0)
|
|
onY = (p.x == 0) && (p.z == 0)
|
|
onZ = (p.x == 0) && (p.y == 0)
|
|
\end{code}
|
|
\todo[inline]{Reflect upon this example.}
|
|
\end{Answer}
|
|
|
|
\paragraph*{Predefined type synonyms} The following type synonyms are
|
|
predefined in Cryptol:
|
|
\begin{Verbatim}
|
|
type Bool = Bit
|
|
type Char = [8]
|
|
type String n = [n]Char
|
|
type Word n = [n]
|
|
\end{Verbatim}
|
|
For instance, a {\tt String n} is simply a sequence of precisely $n$
|
|
8-bit words.\indTSWord\indTSString\indTSBool
|
|
|
|
\todo[inline]{Discussion of \texttt{String} as a type synonym is an
|
|
important example, so more discussion is warranted.}
|
|
|
|
%=====================================================================
|
|
\section{Type classes}\indTypeClasses
|
|
\label{sec:type-classes}
|
|
|
|
\todo[inline]{This section needs a full rewrite.}
|
|
|
|
\todo[inline]{Add discussion of Haskell's type classes and other
|
|
typeclass-like things.}
|
|
|
|
Type classes are a way of describing behaviors shared by multiple
|
|
types. As an example, consider the type of the function {\tt ==}:
|
|
\begin{Verbatim}
|
|
Cryptol> :t (==)
|
|
(==) : {a} (Eq a) => a -> a -> Bit
|
|
\end{Verbatim}
|
|
|
|
This type signature may be read as, ``equality is an operator that
|
|
takes two objects of any single type that can be compared and returns
|
|
a Bit.''
|
|
|
|
Cryptol defines a collection of basic type classes: \texttt{Logic},
|
|
\texttt{Zero}, \texttt{Eq}, \texttt{Cmp}, \texttt{SignedCmp}, \texttt{Ring},
|
|
\texttt{Integral}, \texttt{Field}, \texttt{Round}, and
|
|
\texttt{Literal}. These appear in the type signature of operators and
|
|
functions that require them. If a function you define calls, for
|
|
example, \texttt{+}, on two arguments both of type \texttt{a}, the
|
|
type constraints for \texttt{a} will include \texttt{(Ring a)}.
|
|
|
|
\begin{itemize}
|
|
\item
|
|
The \texttt{Logic} typeclass includes the binary logical operators
|
|
\texttt{\&\&}, \texttt{||}, and \verb+^+, as well as the unary
|
|
operator \verb+~+. Cryptol types made of bits (but not those
|
|
containing unbounded integers) are instances of class \texttt{Logic}.
|
|
|
|
\item
|
|
The \texttt{Zero} typeclass includes the special constant
|
|
\texttt{zero}. The shifting operators \texttt{<<} and \texttt{>>} are
|
|
also in class \texttt{Zero}, because they can shift in zero values.
|
|
All of the built-in types of Cryptol are instances of class
|
|
\texttt{Zero}.
|
|
|
|
\item
|
|
The \texttt{Eq} typeclass includes the equality testing operations
|
|
\texttt{==} and \texttt{!=}. Function types are not in class \texttt{Eq}
|
|
and cannot be compared with \texttt{==}, but Cryptol does provide a
|
|
special pointwise comparison operator for functions, \texttt{(===) :
|
|
\{a b\} (Cmp b) => (a -> b) -> (a -> b) -> a -> Bit}.
|
|
|
|
\item
|
|
The \texttt{Cmp} typeclass includes the binary relation operators
|
|
\texttt{<}, \texttt{>}, \texttt{<=}, \texttt{>=}, as well as the
|
|
binary functions \texttt{min} and \texttt{max}.
|
|
|
|
\item
|
|
The \texttt{SignedCmp} typeclass includes the binary relation
|
|
operators \texttt{<\$}, \texttt{>\$}, \texttt{<=\$}, and
|
|
\texttt{>=\$}. These are like \texttt{<}, \texttt{>}, \texttt{<=}, and
|
|
\texttt{>=}, except that they interpret bitvectors as \emph{signed}
|
|
2's complement numbers, whereas the \texttt{Cmp} operations use the
|
|
\emph{unsigned} ordering. \texttt{SignedCmp} does not contain the
|
|
other atomic numeric types in Cryptol, just bitvectors.
|
|
|
|
\item
|
|
The \texttt{Ring} typeclass includes the binary operators \texttt{+},
|
|
\texttt{-}, \texttt{*}, and the unary operators \texttt{negate}
|
|
and \texttt{fromInteger}. All the numeric types in Cryptol
|
|
are members of \texttt{Ring}.
|
|
|
|
\item
|
|
The \texttt{Integral} typeclass represents values that are ``like
|
|
integers''. It inclues the integral division and modulus operators
|
|
\texttt{/} and \texttt{\%}, and the \texttt{toInteger} casting function.
|
|
The sequence indexing, update and shifting operations
|
|
take index arguments that can be of any \texttt{Integral} type.
|
|
Infinite sequence enumerations \texttt{[x ...]}
|
|
and \texttt{[x, y ...]} are also defined for class \texttt{Integral}.
|
|
Bitvectors and integers members of \texttt{Integral}.
|
|
|
|
\item
|
|
The \texttt{Field} typeclass represents values that, in addition to
|
|
being a \texttt{Ring}, have multiplictive inverses.
|
|
It includes the field division operation \texttt{/.} and the
|
|
\texttt{recip} operation for computing the reciprocol of a value.
|
|
Currently, only type \texttt{Rational} is a member of this class.
|
|
|
|
\item
|
|
The \texttt{Round} typeclass contains types that can be
|
|
rounded to integers. It includes \texttt{floor}, \texttt{ceiling},
|
|
\texttt{trunc}, \texttt{roundAway} and \texttt{roundToEven}
|
|
operations, which are all different ways of rounding values to
|
|
integers. Currently, only type \texttt{Rational} is a member of this class.
|
|
|
|
\item
|
|
The \texttt{Literal} typeclass includes numeric literals.
|
|
\end{itemize}
|
|
|
|
\begin{Exercise}\label{ex:tvar:1}
|
|
Without including an explicit type declaration, define a function
|
|
that Cryptol infers has the following type:
|
|
\begin{Verbatim}
|
|
cmpRing : {a,b} (Eq a, Ring b) => a -> a -> b -> b
|
|
\end{Verbatim}
|
|
\end{Exercise}
|
|
\begin{Answer}\ansref{ex:tvar:1}
|
|
This code:
|
|
\begin{code}
|
|
cmpRing x y z = if x == y then z else z+z
|
|
\end{code}
|
|
yields the inferred type:
|
|
\begin{Verbatim}
|
|
cmpRing : {a, b} (Eq a, Ring b) => a -> a -> b -> b
|
|
\end{Verbatim}
|
|
\end{Answer}
|
|
|
|
%=====================================================================
|
|
\section{Type vs.\ value variables}\indTypeVariables
|
|
\label{sec:type-vs.-value}
|
|
|
|
\todo[inline]{Rewrite this whole section to better clarify object- vs. type
|
|
variables, their scope and limitations, where they can be left
|
|
abstract and when and where they must be concretized, etc.}
|
|
|
|
Its powerful type system is one of the key features of Cryptol. We
|
|
have encountered many aspects of types already. You may have noticed,
|
|
in functions such as \texttt{split}, that when you call a function in
|
|
Cryptol, there are two kinds of parameters you can pass: \textit{value
|
|
variables} and \textit{type variables}.
|
|
|
|
Consider the \texttt{split} function that we previously examined in
|
|
Exercise \autoref{ex:poly:split}. Recall that \texttt{split}'s
|
|
type is:
|
|
\begin{verbatim}
|
|
split : {parts, each, a} (fin each) =>
|
|
[parts * each]a -> [parts][each]a
|
|
\end{verbatim}
|
|
When applying \texttt{split}, one typically specifies a concrete
|
|
value for the formal parameter \texttt{parts}:
|
|
\begin{Verbatim}
|
|
Cryptol> split`{parts=3} [1..12]
|
|
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
|
|
\end{Verbatim}
|
|
In this example, the term {\tt\Verb|`{parts=3}|} passes \texttt{3} to
|
|
the \texttt{parts} type variable argument, and the \texttt{[1..12]} is
|
|
passing a sequence as the first (and only) \textit{value argument}.
|
|
|
|
A \emph{value variable} is the kind of variable you are used to from
|
|
normal programming languages. This kind of variable represents a
|
|
normal run-time value.
|
|
|
|
A \emph{type variable}, on the other hand, allows you to express
|
|
interesting (arithmetic) constraints on \emph{types}. These variables
|
|
express things like lengths of sequences or relationships between
|
|
lengths of sequences. Type variable values are computed
|
|
statically---they never change at runtime.\footnote{In this way,
|
|
they are similar (but more expressive than) templates in languages
|
|
like C++ or Java. If you want to learn more about this area, look up
|
|
the term ``type-level naturals''.}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Positional vs.\ named type
|
|
arguments}\indTypePositionalArguments
|
|
\label{sec:positional-vs.-named}
|
|
|
|
Cryptol permits type variables to be passed either by name (as in {\tt
|
|
\Verb|`{parts=3}|} above), or by position (leaving out the name).
|
|
For functions you define, the position is the order in which the type
|
|
variables are declared in your function's type signature. If you are
|
|
not sure what that is, you can always use the {\tt :t} command to find
|
|
out the position of type variables.
|
|
|
|
For example:
|
|
\begin{Verbatim}
|
|
Cryptol> :t groupBy
|
|
groupBy : {each, parts, elem}
|
|
(fin each) => [parts * each]elem
|
|
-> [parts][each]elem
|
|
\end{Verbatim}
|
|
tells us that that {\tt parts} is in the second position of {\tt
|
|
groupBy}'s type signature, so the positional-style call equivalent
|
|
to our example is:
|
|
\begin{Verbatim}
|
|
Cryptol> groupBy`{_,3}[1..12]
|
|
\end{Verbatim}
|
|
|
|
Note the use of an underscore in order to pass \texttt{3} in the
|
|
second position. Positional arguments are most often used when the
|
|
type argument is the first argument and when the name of the argument
|
|
does not add clarity. The {\tt groupBy\Verb|`{_,3}|} is not as
|
|
self-explanatory as {\tt groupBy\Verb|`{parts=3}|}. On the other hand, our
|
|
use of positional arguments to {\tt take} in previous chapters is very
|
|
clear, as in:
|
|
\begin{Verbatim}
|
|
Cryptol> take`{3}[1..12]
|
|
[1, 2, 3]
|
|
\end{Verbatim}
|
|
|
|
\begin{tip}
|
|
Cryptol programs that use named arguments are more maintainable and
|
|
robust during program evolution. E.g., you can reorder parameters or
|
|
refactor function definitions much more easily if invocations of
|
|
those functions use named, rather than positional, arguments.
|
|
\end{tip}
|
|
|
|
\todo[inline]{What are the implications to type inference, especially
|
|
resolution, in the presence of positional arguments.}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Type context vs.\ variable context}\indTypeContext
|
|
\label{sec:type-context-vs}
|
|
|
|
You have seen, in the discussion of type variables above, that Cryptol
|
|
has two kinds of variables---type variables and value variables. Type
|
|
variables normally show up in type signatures, and value variables
|
|
normally show up in function definitions. Sometimes you may want to
|
|
use a type variable in a context where value variables would normally
|
|
be used. To do this, use the backtick character {\tt \Verb|`|}.
|
|
|
|
The definition of the built-in \texttt{length} function is a good example
|
|
of the use of backtick:
|
|
\begin{Verbatim}
|
|
length : {n, a, b} (fin n, Literal n b) => [n]a -> b
|
|
length _ = `n
|
|
\end{Verbatim}
|
|
|
|
\begin{tip}
|
|
Note there are some subtle things going on in the above definition
|
|
of \texttt{length}. First, arithmetic constraints on types are
|
|
position-independent; properties of formal parameters early in a
|
|
signature can depend upon those late in a signature. Second, type
|
|
constraints can refer to not only other functions, but recursively
|
|
to the function that is being defined (either directly, or
|
|
transitively).
|
|
|
|
Type constraints can get pretty crazy in practice, especially deep
|
|
in the signature of crypto code subsystems. Our suggestion is that
|
|
you should not chase the dragon's tail of feedback from the
|
|
typechecker in attempting to massage your specification's types for
|
|
verification. Instead, think carefully about the meaning and
|
|
purpose of the concepts in your specification, introduce appropriate
|
|
type synonyms, and ensure that the specification is clear and
|
|
precise. Trust that the interpreter and the verifier will do the
|
|
right thing.
|
|
\end{tip}
|
|
|
|
The bounds in a finite sequence literal (such as \texttt{[1 ..\ 10]}) in
|
|
Cryptol are type-level values because the length of a sequence is part
|
|
of its type. Only type-level values can appear in a finite sequence
|
|
definition. You cannot write \texttt{[a ..\ b]} where either \texttt{a} or
|
|
\texttt{b} are arguments to a function. On the other hand, an infinite
|
|
sequence's type is fixed (\texttt{[inf]a}), so the initial value in an
|
|
infinite sequence can be a runtime variable or a type variable, but
|
|
type variables are escaped here using a {\tt \Verb|`|}.
|
|
|
|
\todo[inline]{Add an example of this here. Rewrite if something great
|
|
occurs to us.}
|
|
|
|
\todo[inline]{A proper discussion of type-context vs.~value-context is
|
|
necessary here, and it should be formalized as part of the type
|
|
system and type-inference algorithm, of course.}
|
|
|
|
This is probably obvious, but there is no way to get a value variable
|
|
to appear in a type context. Types must be known at ``compile time,''
|
|
and (non-literal) values are not, so there is no way to use them in
|
|
that way.
|
|
|
|
\todo[inline]{It is more subtle than this because we do not have a proper
|
|
semantic for when arithmetic terms in types (or expressions, for
|
|
that matter!) are evaluated.}
|
|
|
|
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
\subsection{Inline argument type declarations}\indTypeInline
|
|
\label{sec:inline-argument-type}
|
|
|
|
So far when we have defined a function, we have declared the type of
|
|
its arguments and its return value in a separate type declaration.
|
|
When you are initially writing code, you might not know exactly what a
|
|
function's full type is (including the constraints), but you may know
|
|
(and need to express) the types of the function's arguments. Cryptol's
|
|
syntax for this should look familiar:
|
|
\begin{code}
|
|
addBytes (x:[8]) (y:[8]) = x + y
|
|
\end{code}
|
|
|
|
This defines a function that takes two bytes as input, and returns their sum.
|
|
Note that the use of parentheses \texttt{( )} is mandatory.
|
|
|
|
Here is a more interesting example:
|
|
\begin{code}
|
|
myWidth (x:[w]a) = `w
|
|
\end{code}
|
|
|
|
\todo[inline]{Why is this more interesting? What are the reflections the
|
|
reader should have?}
|
|
|
|
%=====================================================================
|
|
\section{Type constraint synonyms}
|
|
|
|
Sometimes programs have certain combinations of type constraints that
|
|
appear over and over in many places. For convenience, Cryptol allows
|
|
the programmer to declare named sets of type constraints that can be
|
|
used in other function type signatures. Typically a named type
|
|
constraint will have one or more type parameters. The syntax is very
|
|
similar to a type synonym declaration:
|
|
|
|
\begin{code}
|
|
type constraint myConstraint a b = (fin a, fin b, b >= width a)
|
|
\end{code}
|
|
|
|
Wherever a type constraint synonym is used, it is as if its definition
|
|
is expanded in place. So the following two signatures would be
|
|
equivalent:
|
|
|
|
\begin{code}
|
|
myWidth : {bits,len,elem} (fin len, fin bits, bits >= width len) => [len] elem -> [bits]
|
|
myWidth : {bits,len,elem} (myConstraint len bits) => [len] elem -> [bits]
|
|
\end{code}
|
|
|
|
%=====================================================================
|
|
\section{Program structure with modules}
|
|
|
|
When a cryptographic specification gets very large it can make sense
|
|
to decompose its functions into modules.\indModuleSystem\indImport
|
|
Doing this well encourages
|
|
code reuse, so it's a generally good thing to do. Cryptol's module
|
|
system is simple and easy to use. Here's a quick overview:
|
|
|
|
A module's name should be the same as the filename the module is defined in,
|
|
and each file may contain only a single module. For example, the
|
|
\verb+utilities+ module should be defined in a file called
|
|
\verb+utilities.cry+. To specify that a file defines a module, its first
|
|
non-commented line should be:
|
|
|
|
\begin{verbatim}
|
|
module utilities where
|
|
\end{verbatim}
|
|
|
|
After that the variables and functions you define will be contained
|
|
(in this example) in the {\it utilities} module.
|
|
|
|
In the code where you want to use a module, you \verb+import+ it like this:
|
|
\begin{verbatim}
|
|
import utilities
|
|
\end{verbatim}
|
|
|
|
Cryptol will look for the file \verb+utilities.cry+ in the current directory. Once you've imported a module, all of its variables and functions are available to use in your code.
|
|
|
|
If you're writing a module that has both {\it private} and {\it public}
|
|
definitions, you can hide the ones that shouldn't be exported to modules
|
|
that include it by using the \verb+private+ keyword, like this:\indPrivate
|
|
|
|
\begin{verbatim}
|
|
private internalDouble x = x + x
|
|
exportedDouble = x * 2
|
|
\end{verbatim}
|
|
|
|
As you can tell, by default definitions are exported to including modules.
|
|
|
|
For a large project it can be convenient to place modules in a directory
|
|
structure. In this case, the directory structure becomes part of the modules'
|
|
names. For example, when placing \verb+SHA3.cry+ in the \verb+Hash+ directory and
|
|
accessing it from \verb+HMAC.cry+ you would need to name the modules
|
|
accordingly:
|
|
|
|
\begin{verbatim}
|
|
|
|
sha3 : {n} (fin n) => [n] -> [512]
|
|
sha3 = error "Stubbed, for demonstration only: sha3-512"
|
|
|
|
blocksize : {n} (fin n, n >= 10) => [n]
|
|
blocksize = 576
|
|
\end{verbatim}
|
|
|
|
\begin{verbatim}
|
|
module Hash::SHA3 where
|
|
import Hash::SHA3
|
|
|
|
hmac : {keySize, msgSize} (fin keySize, fin msgSize) => [keySize] -> [msgSize] -> [512]
|
|
hmac k m = sha3 (ko # sha3 (ki # m))
|
|
where ko = zipWith (^) kFull (join (repeat 0x5c))
|
|
ki = zipWith (^) kFull (join (repeat 0x36))
|
|
kFull = if `keySize == blocksize
|
|
then take (k#zero)
|
|
else sha3 k
|
|
\end{verbatim}
|
|
|
|
Finally, if you're importing a module that defines something with
|
|
a name that you would like to define in your code, you can do a
|
|
{\it qualified} import of that module like this:
|
|
|
|
\begin{verbatim}
|
|
import utilities as util
|
|
\end{verbatim}
|
|
|
|
Now, instead of all the definitions being available in your module,
|
|
they are qualified with the name you provided, in this case \verb+util+.
|
|
This means you will prefix those names with \verb+util::+ when you call them,
|
|
and the unqualified names are able to be defined in your own code.
|
|
|
|
\begin{verbatim}
|
|
import utilities as util
|
|
// let's say utililities.cry defines "all", and we want to use
|
|
// it in our refined definition of all:
|
|
all xs = util::all xs && (length xs) > 0
|
|
\end{verbatim}
|
|
|
|
%=====================================================================
|
|
\section{The road ahead}
|
|
\label{sec:road-ahead}
|
|
|
|
In this introductory chapter, we have seen essentially all of the
|
|
language elements in Cryptol. The concepts go deeper, of course, but
|
|
you now have enough knowledge to tackle large Cryptol programming
|
|
tasks. As with any new language, the more exercises you do, the more
|
|
you will feel comfortable with the concepts. In fact, we will take
|
|
that point of view in the remainder of this document to walk you
|
|
through a number of different examples (both small and large),
|
|
employing the concepts we have seen thus far.
|
|
|
|
%%% Local Variables:
|
|
%%% mode: latex
|
|
%%% TeX-master: "../main/Cryptol.tex"
|
|
%%% End:
|