Update syntax appendix of Cryptol book.

This commit is contained in:
Brian Huffman 2018-07-20 18:13:15 -07:00
parent 1eaabf87aa
commit 863c165c66
3 changed files with 352 additions and 100 deletions

View File

@ -6,7 +6,7 @@ are indented more than the beginning of a declaration belong to that
declaration, while lines of text that are indented less terminate a
group of declarations. Groups of declarations appear at the top level of
a Cryptol file, and inside \texttt{where} blocks in expressions. For
example, consider the following declaration group
example, consider the following declaration group:
\begin{verbatim}
f x = x + y + z
@ -19,7 +19,7 @@ g y = y
This group has two declarations, one for \texttt{f} and one for
\texttt{g}. All the lines between \texttt{f} and \texttt{g} that are
indented more then \texttt{f} belong to \texttt{f}.
indented more than \texttt{f} belong to \texttt{f}.
This example also illustrates how groups of declarations may be nested
within each other. For example, the \texttt{where} expression in the
@ -66,16 +66,14 @@ Built-in Operators}\label{keywords-and-built-in-operators}}
The following identifiers have special meanings in Cryptol, and may not
be used for programmer defined names:
\textless{}!--- The table below can be generated by running
\texttt{chop.hs} on this list: Arith Bit Cmp False Inf True else export
extern fin if import inf lg2 max min module newtype pragma property then
type where width ---\textgreater{}
\todo[inline]{ The table below can be generated by running
\texttt{chop.hs} on this list: else extern if private include module newtype pragma property then type where let import as hiding newtype infixl infixr infix primitive parameter constraint }
\begin{verbatim}
Arith Inf extern inf module then
Bit True fin lg2 newtype type
Cmp else if max pragma where
False export import min property width
else include property let newtype primitive
extern module then import infixl parameter
if newtype type as infixr constraint
private pragma where hiding infix
\end{verbatim}
The following table contains Cryptol's operators and their associativity
@ -92,20 +90,25 @@ Operator & Associativity\tabularnewline
\midrule
\endhead
\texttt{-\textgreater{}} (types) & right\tabularnewline
\texttt{==\textgreater{}} & right\tabularnewline
\texttt{\textbackslash{}/} & right\tabularnewline
\texttt{/\textbackslash{}} & right\tabularnewline
\texttt{==} \texttt{!=} \texttt{===} \texttt{!===} & not associative\tabularnewline
\texttt{\textgreater{}} \texttt{\textless{}} \texttt{\textless{}=} \texttt{\textgreater{}=}
\texttt{\textgreater{}\$} \texttt{\textless{}\$} \texttt{\textless{}=\$} \texttt{\textgreater{}=\$}
& not associative\tabularnewline
\texttt{\textbar{}\textbar{}} & right\tabularnewline
\texttt{\&\&} & right\tabularnewline
\texttt{!=} \texttt{==} & not associative\tabularnewline
\texttt{\textgreater{}} \texttt{\textless{}} \texttt{\textless{}=}
\texttt{\textgreater{}=} & not associative\tabularnewline
\texttt{\^{}} & left\tabularnewline
\texttt{\#} & left\tabularnewline
\texttt{\&\&} & right\tabularnewline
\texttt{\#} & right\tabularnewline
\texttt{\textgreater{}\textgreater{}} \texttt{\textless{}\textless{}}
\texttt{\textgreater{}\textgreater{}\textgreater{}}
\texttt{\textless{}\textless{}\textless{}} & left\tabularnewline
\texttt{\textless{}\textless{}\textless{}}
\texttt{\textgreater{}\textgreater{}\$} & left\tabularnewline
\texttt{+} \texttt{-} & left\tabularnewline
\texttt{*} \texttt{/} \texttt{\%} & left\tabularnewline
\texttt{\^{}\^{}} & right\tabularnewline
\texttt{!} \texttt{!!} \texttt{@} \texttt{@@} & left\tabularnewline
\texttt{@} \texttt{@@} \texttt{!} \texttt{!!} & left\tabularnewline
(unary) \texttt{-} \texttt{\textasciitilde{}} & right\tabularnewline
\bottomrule
\end{longtable}
@ -128,22 +131,19 @@ Examples:
0xfe // Hexadecimal literal
\end{verbatim}
Numeric literals represent finite bit sequences (i.e., they have type
\texttt{{[}n{]}}). Using binary, octal, and hexadecimal notation results
in bit sequences of a fixed length, depending on the number of digits in
the literal. Decimal literals are overloaded, and so the length of the
sequence is inferred from context in which the literal is used.
Examples:
Numeric literals in binary, octal, or hexadecimal notation result in
bit sequences of a fixed length (i.e., they have type \texttt{[n]} for
some \texttt{n}). The length is determined by the base and the number
of digits in the literal. Decimal literals are overloaded, and so the
type is inferred from context in which the literal is used. Examples:
\begin{verbatim}
0b1010 // : [4], 1 * number of digits
0o1234 // : [12], 3 * number of digits
0x1234 // : [16], 4 * number of digits
10 // : {n}. (fin n, n >= 4) => [n]
// (need at least 4 bits)
0 // : {n}. (fin n) => [n]
10 // : {a}. (Literal 10 a) => a
// a = Integer or [n] where n >= width 10
\end{verbatim}
\section{Bits}\label{bits}
@ -296,17 +296,19 @@ Operator & Description\tabularnewline
\endhead
\texttt{\#} & Sequence concatenation\tabularnewline
\texttt{\textgreater{}\textgreater{}} \texttt{\textless{}\textless{}} &
Shift (right,left)\tabularnewline
Shift (right, left)\tabularnewline
\texttt{\textgreater{}\textgreater{}\textgreater{}}
\texttt{\textless{}\textless{}\textless{}} & Rotate
(right,left)\tabularnewline
\texttt{@} \texttt{!} & Access elements (front,back)\tabularnewline
(right, left)\tabularnewline
\texttt{@} \texttt{!} & Access elements (front, back)\tabularnewline
\texttt{@@} \texttt{!!} & Access sub-sequence
(front,back)\tabularnewline
(front, back)\tabularnewline
\texttt{update} \texttt{updateEnd} & Update the value of a sequence at a location (front, back)\tabularnewline
\texttt{updates} \texttt{updatesEnd} & Update multiple values of a sequence (front, back)\tabularnewline
\bottomrule
\end{longtable}
There are also lifted point-wise operations.
There are also lifted pointwise operations.
\begin{verbatim}
[p1, p2, p3, p4] // Sequence pattern
@ -387,3 +389,288 @@ f,g : {a,b} (fin a) => [a] b
\begin{verbatim}
type T a b = [a] b
\end{verbatim}
\section{Module Imports}
To use the definitions from one module in another module, we use
\texttt{import} declarations:
\begin{verbatim}
// Provide some definitions
module M where
f : [8]
f = 2
// Uses definitions from `M`
module N where
import M // import all definitions from `M`
g = f // `f` was imported from `M`
\end{verbatim}
\section{Import Lists}
Sometimes, we may want to import only some of the definitions
from a module. To do so, we use an import declaration with
an \textit{import list}.
\begin{verbatim}
module M where
f = 0x02
g = 0x03
h = 0x04
module N where
import M(f,g) // Imports only `f` and `g`, but not `h`
x = f + g
\end{verbatim}
Using explicit import lists helps reduce name collisions.
It also tends to make code easier to understand, because
it makes it easy to see the source of definitions.
\section{Hiding Imports}
Sometimes a module may provide many definitions, and we want to use
most of them but with a few exceptions (e.g., because those would
result to a name clash). In such situations it is convenient
to use a \textit{hiding} import:
\begin{verbatim}
module M where
f = 0x02
g = 0x03
h = 0x04
module N where
import M hiding (h) // Import everything but `h`
x = f + g
\end{verbatim}
\section{Qualified Module Imports}
Another way to avoid name collisions is by using a
\textit{qualified} import.
\begin{verbatim}
module M where
f : [8]
f = 2
module N where
import M as P
g = P::f
// `f` was imported from `M`
// but when used it needs to be prefixed by the qualified `P`
\end{verbatim}
Qualified imports make it possible to work with definitions
that happen to have the same name but are defined in different modules.
Qualified imports may be combined with import lists or hiding clauses:
\begin{verbatim}
import A as B (f) // introduces B::f
import X as Y hiding (f) // introduces everything but `f` from X
// using the prefix `X`
\end{verbatim}
It is also possible the use the same qualifier prefix for imports
from different modules. For example:
\begin{verbatim}
import A as B
import X as B
\end{verbatim}
Such declarations will introduces all definitions from \texttt{A} and \texttt{X}
but to use them, you would have to qualify using the prefix \texttt{B:::}.
\section{Private Blocks}
In some cases, definitions in a module might use helper
functions that are not intended to be used outside the module.
It is good practice to place such declarations in \textit{private blocks}:
\begin{verbatim}
module M where
f : [8]
f = 0x01 + helper1 + helper2
private
helper1 : [8]
helper1 = 2
helper2 : [8]
helper2 = 3
\end{verbatim}
The keyword \texttt{private} introduce a new layout scope, and all declarations
in the block are considered to be private to the module. A single module
may contain multiple private blocks. For example, the following module
is equivalent to the previous one:
\begin{verbatim}
module M where
f : [8]
f = 0x01 + helper1 + helper2
private
helper1 : [8]
helper1 = 2
private
helper2 : [8]
helper2 = 3
\end{verbatim}
\section{Parameterized Modules}
\begin{verbatim}
module M where
parameter
type n : # // `n` is a numeric type parameter
type constraint (fin n, n >= 1)
// Assumptions about the parameter
x : [n] // A value parameter
// This definition uses the parameters.
f : [n]
f = 1 + x
\end{verbatim}
\section{Named Module Instantiations}
One way to use a parameterized module is through a named instantiation:
\begin{verbatim}
// A parameterized module
module M where
parameter
type n : #
x : [n]
y : [n]
f : [n]
f = x + y
// A module instantiation
module N = M where
type n = 32
x = 11
y = helper
helper = 12
\end{verbatim}
The second module, \texttt{N}, is computed by instantiating the parameterized
module \texttt{M}. Module \texttt{N} will provide the exact same definitions as \texttt{M},
except that the parameters will be replaced by the values in the body
of \texttt{N}. In this example, \texttt{N} provides just a single definition, \texttt{f}.
Note that the only purpose of the body of \texttt{N} (the declarations
after the \texttt{where} keyword) is to define the parameters for \texttt{M}.
\section{Parameterized Instantiations}
It is possible for a module instantiations to be itself parameterized.
This could be useful if we need to define some of a module's parameters
but not others.
\begin{verbatim}
// A parameterized module
module M where
parameter
type n : #
x : [n]
y : [n]
f : [n]
f = x + y
// A parameterized instantiation
module N = M where
parameter
x : [32]
type n = 32
y = helper
helper = 12
\end{verbatim}
In this case \texttt{N} has a single parameter \texttt{x}. The result of instantiating
\texttt{N} would result in instantiating \texttt{M} using the value of \texttt{x} and \texttt{12}
for the value of \texttt{y}.
\section{Importing Parameterized Modules}
It is also possible to import a parameterized module without using
a module instantiation:
\begin{verbatim}
module M where
parameter
x : [8]
y : [8]
f : [8]
f = x + y
module N where
import `M
g = f { x = 2, y = 3 }
\end{verbatim}
A \textit{backtick} at the start of the name of an imported module indicates
that we are importing a parameterized module. In this case, Cryptol
will import all definitions from the module as usual, however every
definition will have some additional parameters corresponding to
the parameters of a module. All value parameters are grouped in a record.
This is why in the example \texttt{f} is applied to a record of values,
even though its definition in \texttt{M} does not look like a function.

View File

@ -159,10 +159,11 @@ have defined, along with their types.
\textbf{Option} & \textbf{Default value} & \textbf{Meaning} \\
\hline
\texttt{ascii} & \texttt{off} & print sequences of bytes as a string \\
\texttt{base} & \texttt{10} & numeric base for printing words \\
\texttt{base} & \texttt{16} & numeric base for printing words \\
\texttt{debug} & \texttt{off} & whether to print verbose debugging information \\
\texttt{infLength} & \texttt{5} & number of elements to show from an infinite sequence \\
\texttt{prover} & \texttt{z3} & which SMT solver to use for \texttt{:prove} \\
\texttt{satNum} & \texttt{1} & maximum number of solutions to show for \texttt{:sat} \\
\texttt{tests} & \texttt{100} & number of tests to run for \texttt{:check} \\
\texttt{warnDefaulting} & \texttt{on} & \todo[inline]{talk to Iavor} \\
\hline

View File

@ -12,7 +12,7 @@ declaration belong to that declaration, while lines of text that are
indented less terminate a group of declarations. Groups of
declarations appear at the top level of a Cryptol file, and inside
`where` blocks in expressions. For example, consider the following
declaration group
declaration group:
f x = x + y + z
where
@ -21,8 +21,8 @@ declaration group
g y = y
This group has two declaration, one for `f` and one for `g`. All the
lines between `f` and `g` that are indented more then `f` belong to
This group has two declarations, one for `f` and one for `g`. All the
lines between `f` and `g` that are indented more than `f` belong to
`f`.
This example also illustrates how groups of declarations may be nested
@ -66,23 +66,11 @@ The following identifiers have special meanings in Cryptol, and may
not be used for programmer defined names:
<!--- The table below can be generated by running `chop.hs` on this list:
Arith
Bit
Cmp
False
Inf
SignedCmp
True
else
export
extern
fin
if
import
inf
lg2
max
min
private
include
module
newtype
pragma
@ -90,13 +78,23 @@ property
then
type
where
width
let
import
as
hiding
newtype
infixl
infixr
infix
primitive
parameter
constraint
--->
Arith Inf export import min property width
Bit SignedCmp extern inf module then
Cmp True fin lg2 newtype type
False else if max pragma where
else include property let newtype primitive
extern module then import infixl parameter
if newtype type as infixr constraint
private pragma where hiding infix
The following table contains Cryptol's operators and their
associativity with lowest precedence operators first, and highest
@ -110,9 +108,9 @@ Operator Associativity
`->` (types) right
`!=` `==` not associative
`>` `<` `<=` `>=` `<$` `>$` `<=$` `>=$` not associative
`||` right
`||` right
`^` left
`&&` right
`&&` right
`#` right
`>>` `<<` `>>>` `<<<` `>>$` left
`+` `-` left
@ -151,10 +149,8 @@ Examples:
0o1234 // : [12], 3 * number of digits
0x1234 // : [16], 4 * number of digits
10 // : {n}. (fin n, n >= 4) => [n]
// (need at least 4 bits)
0 // : {n}. (fin n) => [n]
10 // : {a}. (Literal 10 a) => a
// a = Integer or [n] where n >= width 10
Bits
====
@ -281,13 +277,13 @@ sequences are value expressions.
Operator Description
--------------------------- -----------
`#` Sequence concatenation
`>>` `<<` Shift (right,left)
`>>>` `<<<` Rotate (right,left)
`>>` `<<` Shift (right, left)
`>>>` `<<<` Rotate (right, left)
`>>$` Arithmetic right shift (on bitvectors only)
`@` `!` Access elements (front,back)
`@@` `!!` Access sub-sequence (front,back)
`update` `updateEnd` Update the value of a sequence at a location (front,back)
`updates` `updatesEnd` Update multiple values of a sequence (front,back)
`@` `!` Access elements (front, back)
`@@` `!!` Access sub-sequence (front, back)
`update` `updateEnd` Update the value of a sequence at a location (front, back)
`updates` `updatesEnd` Update multiple values of a sequence (front, back)
Table: Sequence operations.
@ -570,7 +566,7 @@ Parameterized Modules
Named Module Instantiations
===========================
One way to use a parameterized module is trough a named instantiation:
One way to use a parameterized module is through a named instantiation:
// A parameterized module
module M where
@ -668,35 +664,3 @@ the parameters of a module. All value parameters are grouped in a record.
This is why in the example `f` is applied to a record of values,
even though its definition in `M` does not look like a function.