mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-09-11 22:17:18 +03:00
Update Syntax.md and re-sync it with Syntax.tex
Note that Syntax.tex should be generated automatically
This commit is contained in:
parent
1b780c21e1
commit
6a8c6c3134
Binary file not shown.
@ -1,2 +1,2 @@
|
||||
Syntax.tex : ../../Syntax.md
|
||||
pandoc ../../Syntax.md --to latex > Syntax.tex
|
||||
Syntax.tex : ../../Syntax.md README
|
||||
bash -c 'cat README <(pandoc ../../Syntax.md --to latex)' > Syntax.tex
|
||||
|
4
docs/ProgrammingCryptol/appendices/README
Normal file
4
docs/ProgrammingCryptol/appendices/README
Normal file
@ -0,0 +1,4 @@
|
||||
% IMPORTANT: The file Syntax.tex is generated automatically from the
|
||||
% markdown in ../../Syntax.md. If you make changes, please make them
|
||||
% there and then regenarte the .tex file using the Makefile.
|
||||
|
@ -1,3 +1,7 @@
|
||||
% IMPORTANT: The file Syntax.tex is generated automatically from the
|
||||
% markdown in ../../Syntax.md. If you make changes, please make them
|
||||
% there and then regenarte the .tex file using the Makefile.
|
||||
|
||||
\section{Layout}\label{layout}
|
||||
|
||||
Groups of declarations are organized based on indentation. Declarations
|
||||
@ -51,7 +55,7 @@ The following characters may be an English letter, a decimal digit,
|
||||
underscore (\texttt{\_}), or a prime (\texttt{\textquotesingle{}}). Some
|
||||
identifiers have special meaning in the language, so they may not be
|
||||
used in programmer-defined names (see
|
||||
\hyperref[keywords-and-built-in-operators]{Keywords}).
|
||||
\protect\hyperlink{keywords-and-built-in-operators}{Keywords}).
|
||||
|
||||
Examples:
|
||||
|
||||
@ -60,26 +64,23 @@ name name1 name' longer_name
|
||||
Name Name2 Name'' longerName
|
||||
\end{verbatim}
|
||||
|
||||
\hyperdef{}{keywords-and-built-in-operators}{\section{Keywords and
|
||||
\hypertarget{keywords-and-built-in-operators}{\section{Keywords and
|
||||
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:
|
||||
|
||||
\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}
|
||||
else include property let newtype primitive
|
||||
extern module then import infixl parameter
|
||||
if newtype type as infixr constraint
|
||||
private pragma where hiding infix
|
||||
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
|
||||
with lowest precedence operators first, and highest precedence last.
|
||||
|
||||
\begin{longtable}[c]{@{}ll@{}}
|
||||
\begin{longtable}[]{@{}ll@{}}
|
||||
\caption{Operator precedences.}\tabularnewline
|
||||
\toprule
|
||||
Operator & Associativity\tabularnewline
|
||||
@ -89,14 +90,15 @@ Operator & Associativity\tabularnewline
|
||||
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{==} \texttt{!=} \texttt{===} \texttt{!==} & not
|
||||
associative\tabularnewline
|
||||
\texttt{\textgreater{}} \texttt{\textless{}} \texttt{\textless{}=}
|
||||
\texttt{\textgreater{}=} \texttt{\textless{}\$}
|
||||
\texttt{\textgreater{}\$} \texttt{\textless{}=\$}
|
||||
\texttt{\textgreater{}=\$} & not associative\tabularnewline
|
||||
\texttt{\textbar{}\textbar{}} & right\tabularnewline
|
||||
\texttt{\^{}} & left\tabularnewline
|
||||
\texttt{\&\&} & right\tabularnewline
|
||||
@ -106,20 +108,21 @@ Operator & Associativity\tabularnewline
|
||||
\texttt{\textless{}\textless{}\textless{}}
|
||||
\texttt{\textgreater{}\textgreater{}\$} & left\tabularnewline
|
||||
\texttt{+} \texttt{-} & left\tabularnewline
|
||||
\texttt{*} \texttt{/} \texttt{\%} & left\tabularnewline
|
||||
\texttt{*} \texttt{/} \texttt{\%} \texttt{/\$} \texttt{\%\$} &
|
||||
left\tabularnewline
|
||||
\texttt{\^{}\^{}} & right\tabularnewline
|
||||
\texttt{@} \texttt{@@} \texttt{!} \texttt{!!} & left\tabularnewline
|
||||
(unary) \texttt{-} \texttt{\textasciitilde{}} & right\tabularnewline
|
||||
\bottomrule
|
||||
\end{longtable}
|
||||
|
||||
\hyperdef{}{built-in-type-operators}{\section{Built-in Type-level
|
||||
Operators}\label{built-in-type-operators}}
|
||||
\section{Built-in Type-level
|
||||
Operators}\label{built-in-type-level-operators}
|
||||
|
||||
Cryptol includes a variety of operators that allow computations on
|
||||
the numeric types used to specify the sizes of sequences.
|
||||
Cryptol includes a variety of operators that allow computations on the
|
||||
numeric types used to specify the sizes of sequences.
|
||||
|
||||
\begin{longtable}[c]{@{}ll@{}}
|
||||
\begin{longtable}[]{@{}ll@{}}
|
||||
\caption{Type-level operators}\tabularnewline
|
||||
\toprule
|
||||
Operator & Meaning\tabularnewline
|
||||
@ -133,11 +136,13 @@ Operator & Meaning\tabularnewline
|
||||
\texttt{-} & Size subtraction\tabularnewline
|
||||
\texttt{*} & Size multiplication\tabularnewline
|
||||
\texttt{/} & Size division\tabularnewline
|
||||
\verb+/^+ & Size ceiling division (\texttt{/} rounded up)\tabularnewline
|
||||
\verb+%+ & Size modulus\tabularnewline
|
||||
\verb+%^+ & Size ceiling modulus (\verb+%+ rounded up)\tabularnewline
|
||||
\verb+^^+ & Size exponentiation\tabularnewline
|
||||
\texttt{lg2} & Size logarithm (base-2)\tabularnewline
|
||||
\texttt{/\^{}} & Size ceiling division (\texttt{/} rounded
|
||||
up)\tabularnewline
|
||||
\texttt{\%} & Size modulus\tabularnewline
|
||||
\texttt{\%\^{}} & Size ceiling modulus (\texttt{\%} rounded
|
||||
up)\tabularnewline
|
||||
\texttt{\^{}\^{}} & Size exponentiation\tabularnewline
|
||||
\texttt{lg2} & Size logarithm (base 2)\tabularnewline
|
||||
\texttt{width} & Size width (\texttt{lg2} rounded up)\tabularnewline
|
||||
\texttt{max} & Size maximum\tabularnewline
|
||||
\texttt{min} & Size minimum\tabularnewline
|
||||
@ -162,11 +167,11 @@ Examples:
|
||||
0xfe // Hexadecimal literal
|
||||
\end{verbatim}
|
||||
|
||||
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:
|
||||
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
|
||||
@ -183,7 +188,7 @@ The type \texttt{Bit} has two inhabitants: \texttt{True} and
|
||||
\texttt{False}. These values may be combined using various logical
|
||||
operators, or constructed as results of comparisons.
|
||||
|
||||
\begin{longtable}[c]{@{}lll@{}}
|
||||
\begin{longtable}[]{@{}lll@{}}
|
||||
\caption{Bit operations.}\tabularnewline
|
||||
\toprule
|
||||
Operator & Associativity & Description\tabularnewline
|
||||
@ -193,17 +198,22 @@ Operator & Associativity & Description\tabularnewline
|
||||
Operator & Associativity & Description\tabularnewline
|
||||
\midrule
|
||||
\endhead
|
||||
\texttt{\textbar{}\textbar{}} & right & Logical or\tabularnewline
|
||||
\texttt{\&\&} & right & Logical and\tabularnewline
|
||||
\texttt{==\textgreater{}} & right & Short-cut implication\tabularnewline
|
||||
\texttt{\textbackslash{}/} & right & Short-cut or\tabularnewline
|
||||
\texttt{/\textbackslash{}} & right & Short-cut and\tabularnewline
|
||||
\texttt{!=} \texttt{==} & none & Not equals, equals\tabularnewline
|
||||
\texttt{\textgreater{}} \texttt{\textless{}} \texttt{\textless{}=}
|
||||
\texttt{\textgreater{}=} & none & Comparisons\tabularnewline
|
||||
\texttt{\textgreater{}=} \texttt{\textless{}\$}
|
||||
\texttt{\textgreater{}\$} \texttt{\textless{}=\$}
|
||||
\texttt{\textgreater{}=\$} & none & Comparisons\tabularnewline
|
||||
\texttt{\textbar{}\textbar{}} & right & Logical or\tabularnewline
|
||||
\texttt{\^{}} & left & Exclusive-or\tabularnewline
|
||||
\texttt{\&\&} & right & Logical and\tabularnewline
|
||||
\texttt{\textasciitilde{}} & right & Logical negation\tabularnewline
|
||||
\bottomrule
|
||||
\end{longtable}
|
||||
|
||||
\section{Multi-way Conditionals}\label{multiway-conditionals}
|
||||
\section{Multi-way Conditionals}\label{multi-way-conditionals}
|
||||
|
||||
The \texttt{if\ ...\ then\ ...\ else} construct can be used with
|
||||
multiple branches. For example:
|
||||
@ -220,8 +230,8 @@ x = if y % 2 == 0 then 1
|
||||
\section{Tuples and Records}\label{tuples-and-records}
|
||||
|
||||
Tuples and records are used for packaging multiple values together.
|
||||
Tuples are enclosed in parentheses, while records are enclosed in
|
||||
curly braces. The components of both tuples and records are separated by
|
||||
Tuples are enclosed in parentheses, while records are enclosed in curly
|
||||
braces. The components of both tuples and records are separated by
|
||||
commas. The components of tuples are expressions, while the components
|
||||
of records are a label and a value separated by an equal sign. Examples:
|
||||
|
||||
@ -315,7 +325,7 @@ Note: the bounds in finite unbounded (those with ..) sequences are type
|
||||
expressions, while the bounds in bounded-finite and infinite sequences
|
||||
are value expressions.
|
||||
|
||||
\begin{longtable}[c]{@{}ll@{}}
|
||||
\begin{longtable}[]{@{}ll@{}}
|
||||
\caption{Sequence operations.}\tabularnewline
|
||||
\toprule
|
||||
Operator & Description\tabularnewline
|
||||
@ -329,13 +339,17 @@ Operator & Description\tabularnewline
|
||||
\texttt{\textgreater{}\textgreater{}} \texttt{\textless{}\textless{}} &
|
||||
Shift (right, left)\tabularnewline
|
||||
\texttt{\textgreater{}\textgreater{}\textgreater{}}
|
||||
\texttt{\textless{}\textless{}\textless{}} & Rotate
|
||||
(right, left)\tabularnewline
|
||||
\texttt{\textless{}\textless{}\textless{}} & Rotate (right,
|
||||
left)\tabularnewline
|
||||
\texttt{\textgreater{}\textgreater{}\$} & Arithmetic right shift (on
|
||||
bitvectors only)\tabularnewline
|
||||
\texttt{@} \texttt{!} & Access elements (front, back)\tabularnewline
|
||||
\texttt{@@} \texttt{!!} & Access sub-sequence
|
||||
(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
|
||||
\texttt{@@} \texttt{!!} & Access sub-sequence (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}
|
||||
|
||||
@ -393,7 +407,7 @@ resulting expression is a finite word, which is sufficiently large to
|
||||
accommodate the value of the type:
|
||||
|
||||
\begin{verbatim}
|
||||
`t : {a} (fin a, a >= width t} => [a]
|
||||
`t : {n} (fin n, n >= width t) => [n]
|
||||
\end{verbatim}
|
||||
|
||||
\section{Explicit Type Annotations}\label{explicit-type-annotations}
|
||||
@ -421,287 +435,311 @@ f,g : {a,b} (fin a) => [a] b
|
||||
type T a b = [a] b
|
||||
\end{verbatim}
|
||||
|
||||
\section{Module Imports}
|
||||
\section{Modules}\label{modules}
|
||||
|
||||
A \textbf{\emph{module}} is used to group some related definitions.
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
|
||||
type T = [8]
|
||||
|
||||
f : [8]
|
||||
f = 10
|
||||
\end{verbatim}
|
||||
|
||||
\section{Hierarchical Module Names}\label{hierarchical-module-names}
|
||||
|
||||
Module may have either simple or \textbf{\emph{hierarchical}} names.
|
||||
Hierarchical names are constructed by gluing together ordinary
|
||||
identifiers using the symbol \texttt{::}.
|
||||
|
||||
\begin{verbatim}
|
||||
module Hash::SHA256 where
|
||||
|
||||
sha256 = ...
|
||||
\end{verbatim}
|
||||
|
||||
The structure in the name may be used to group together related modules.
|
||||
Also, the Cryptol implementation uses the structure of the name to
|
||||
locate the file containing the definition of the module. For example,
|
||||
when searching for module \texttt{Hash::SHA256}, Cryptol will look for a
|
||||
file named \texttt{SHA256.cry} in a directory called \texttt{Hash},
|
||||
contained in one of the directories specified by \texttt{CRYPTOLPATH}.
|
||||
|
||||
\section{Module Imports}\label{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
|
||||
// Provide some definitions
|
||||
module M where
|
||||
|
||||
f : [8]
|
||||
f = 2
|
||||
f : [8]
|
||||
f = 2
|
||||
|
||||
|
||||
// Uses definitions from `M`
|
||||
module N where
|
||||
// Uses definitions from `M`
|
||||
module N where
|
||||
|
||||
import M // import all definitions from `M`
|
||||
import M // import all definitions from `M`
|
||||
|
||||
g = f // `f` was imported 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}.
|
||||
\section{Import Lists}\label{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
|
||||
\textbf{\emph{import list}}.
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
module M where
|
||||
|
||||
f = 0x02
|
||||
g = 0x03
|
||||
h = 0x04
|
||||
f = 0x02
|
||||
g = 0x03
|
||||
h = 0x04
|
||||
|
||||
module N where
|
||||
|
||||
module N where
|
||||
import M(f,g) // Imports only `f` and `g`, but not `h`
|
||||
|
||||
import M(f,g) // Imports only `f` and `g`, but not `h`
|
||||
|
||||
x = f + g
|
||||
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.
|
||||
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}\label{hiding-imports}
|
||||
|
||||
\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:
|
||||
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
|
||||
\textbf{\emph{hiding}} import:
|
||||
|
||||
module M where
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
|
||||
f = 0x02
|
||||
g = 0x03
|
||||
h = 0x04
|
||||
f = 0x02
|
||||
g = 0x03
|
||||
h = 0x04
|
||||
|
||||
|
||||
|
||||
module N where
|
||||
module N where
|
||||
|
||||
import M hiding (h) // Import everything but `h`
|
||||
import M hiding (h) // Import everything but `h`
|
||||
|
||||
x = f + g
|
||||
x = f + g
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
|
||||
\section{Qualified Module Imports}
|
||||
\section{Qualified Module Imports}\label{qualified-module-imports}
|
||||
|
||||
Another way to avoid name collisions is by using a
|
||||
\textit{qualified} import.
|
||||
\textbf{\emph{qualified}} import.
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
module M where
|
||||
|
||||
f : [8]
|
||||
f = 2
|
||||
f : [8]
|
||||
f = 2
|
||||
|
||||
module N where
|
||||
module N where
|
||||
|
||||
import M as P
|
||||
import M as P
|
||||
|
||||
g = P::f
|
||||
// `f` was imported from `M`
|
||||
// but when used it needs to be prefixed by the qualified `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 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`
|
||||
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:
|
||||
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
|
||||
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:::}.
|
||||
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}\label{private-blocks}
|
||||
|
||||
\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}:
|
||||
|
||||
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 \textbf{\emph{private blocks}}:
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
module M where
|
||||
|
||||
f : [8]
|
||||
f = 0x01 + helper1 + helper2
|
||||
f : [8]
|
||||
f = 0x01 + helper1 + helper2
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
helper1 : [8]
|
||||
helper1 = 2
|
||||
helper1 : [8]
|
||||
helper1 = 2
|
||||
|
||||
helper2 : [8]
|
||||
helper2 = 3
|
||||
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:
|
||||
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
|
||||
module M where
|
||||
|
||||
f : [8]
|
||||
f = 0x01 + helper1 + helper2
|
||||
f : [8]
|
||||
f = 0x01 + helper1 + helper2
|
||||
|
||||
private
|
||||
helper1 : [8]
|
||||
helper1 = 2
|
||||
private
|
||||
helper1 : [8]
|
||||
helper1 = 2
|
||||
|
||||
private
|
||||
helper2 : [8]
|
||||
helper2 = 3
|
||||
private
|
||||
helper2 : [8]
|
||||
helper2 = 3
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\section{Parameterized Modules}
|
||||
\section{Parameterized Modules}\label{parameterized-modules}
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
module M where
|
||||
|
||||
parameter
|
||||
type n : # // `n` is a numeric type parameter
|
||||
parameter
|
||||
type n : # // `n` is a numeric type parameter
|
||||
|
||||
type constraint (fin n, n >= 1)
|
||||
// Assumptions about the parameter
|
||||
type constraint (fin n, n >= 1)
|
||||
// Assumptions about the parameter
|
||||
|
||||
x : [n] // A value parameter
|
||||
x : [n] // A value parameter
|
||||
|
||||
// This definition uses the parameters.
|
||||
f : [n]
|
||||
f = 1 + x
|
||||
// This definition uses the parameters.
|
||||
f : [n]
|
||||
f = 1 + x
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\section{Named Module Instantiations}
|
||||
\section{Named Module Instantiations}\label{named-module-instantiations}
|
||||
|
||||
One way to use a parameterized module is through a named instantiation:
|
||||
|
||||
\begin{verbatim}
|
||||
// A parameterized module
|
||||
module M where
|
||||
// A parameterized module
|
||||
module M where
|
||||
|
||||
parameter
|
||||
type n : #
|
||||
x : [n]
|
||||
y : [n]
|
||||
parameter
|
||||
type n : #
|
||||
x : [n]
|
||||
y : [n]
|
||||
|
||||
f : [n]
|
||||
f = x + y
|
||||
f : [n]
|
||||
f = x + y
|
||||
|
||||
|
||||
// A module instantiation
|
||||
module N = M where
|
||||
// A module instantiation
|
||||
module N = M where
|
||||
|
||||
type n = 32
|
||||
x = 11
|
||||
y = helper
|
||||
type n = 32
|
||||
x = 11
|
||||
y = helper
|
||||
|
||||
helper = 12
|
||||
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}.
|
||||
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}.
|
||||
after the \texttt{where} keyword) is to define the parameters for
|
||||
\texttt{M}.
|
||||
|
||||
|
||||
\section{Parameterized Instantiations}
|
||||
\section{Parameterized
|
||||
Instantiations}\label{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
|
||||
// A parameterized module
|
||||
module M where
|
||||
|
||||
parameter
|
||||
type n : #
|
||||
x : [n]
|
||||
y : [n]
|
||||
parameter
|
||||
type n : #
|
||||
x : [n]
|
||||
y : [n]
|
||||
|
||||
f : [n]
|
||||
f = x + y
|
||||
f : [n]
|
||||
f = x + y
|
||||
|
||||
|
||||
// A parameterized instantiation
|
||||
module N = M where
|
||||
// A parameterized instantiation
|
||||
module N = M where
|
||||
|
||||
parameter
|
||||
x : [32]
|
||||
parameter
|
||||
x : [32]
|
||||
|
||||
type n = 32
|
||||
y = helper
|
||||
type n = 32
|
||||
y = helper
|
||||
|
||||
helper = 12
|
||||
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}.
|
||||
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}\label{importing-parameterized-modules}
|
||||
|
||||
\section{Importing Parameterized Modules}
|
||||
|
||||
It is also possible to import a parameterized module without using
|
||||
a module instantiation:
|
||||
It is also possible to import a parameterized module without using a
|
||||
module instantiation:
|
||||
|
||||
\begin{verbatim}
|
||||
module M where
|
||||
module M where
|
||||
|
||||
parameter
|
||||
x : [8]
|
||||
y : [8]
|
||||
parameter
|
||||
x : [8]
|
||||
y : [8]
|
||||
|
||||
f : [8]
|
||||
f = x + y
|
||||
f : [8]
|
||||
f = x + y
|
||||
|
||||
|
||||
module N where
|
||||
module N where
|
||||
|
||||
import `M
|
||||
import `M
|
||||
|
||||
g = f { x = 2, y = 3 }
|
||||
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.
|
||||
A \textbf{\emph{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.
|
||||
|
Binary file not shown.
@ -101,12 +101,11 @@ associativity with lowest precedence operators first, and highest
|
||||
precedence last.
|
||||
|
||||
Operator Associativity
|
||||
--------------- -------------
|
||||
----------------------------------------- -------------
|
||||
`==>` right
|
||||
`\/` right
|
||||
`/\` right
|
||||
`->` (types) right
|
||||
`!=` `==` not associative
|
||||
`==` `!=` `===` `!==` not associative
|
||||
`>` `<` `<=` `>=` `<$` `>$` `<=$` `>=$` not associative
|
||||
`||` right
|
||||
`^` left
|
||||
@ -116,17 +115,41 @@ Operator Associativity
|
||||
`+` `-` left
|
||||
`*` `/` `%` `/$` `%$` left
|
||||
`^^` right
|
||||
`!` `!!` `@` `@@` left
|
||||
`@` `@@` `!` `!!` left
|
||||
(unary) `-` `~` right
|
||||
|
||||
Table: Operator precedences.
|
||||
|
||||
Built-in Type-level Operators
|
||||
=============================
|
||||
|
||||
Cryptol includes a variety of operators that allow computations on
|
||||
the numeric types used to specify the sizes of sequences.
|
||||
|
||||
Operator Meaning
|
||||
-------- -------------------------
|
||||
`+` Size addition
|
||||
`-` Size subtraction
|
||||
`*` Size multiplication
|
||||
`/` Size division
|
||||
`/^` Size ceiling division (`/` rounded up)
|
||||
`%` Size modulus
|
||||
`%^` Size ceiling modulus (`%` rounded up)
|
||||
`^^` Size exponentiation
|
||||
`lg2` Size logarithm (base 2)
|
||||
`width` Size width (`lg2` rounded up)
|
||||
`max` Size maximum
|
||||
`min` Size minimum
|
||||
|
||||
Table: Type-level operators
|
||||
|
||||
|
||||
Numeric Literals
|
||||
================
|
||||
|
||||
Numeric literals may be written in binary, octal, decimal, or
|
||||
hexadecimal notation. The base of a literal is determined by its
|
||||
prefix: `0b` for binary, `0o` for octal, no special prefix for
|
||||
hexadecimal notation. The base of a literal is determined by its prefix:
|
||||
`0b` for binary, `0o` for octal, no special prefix for
|
||||
decimal, and `0x` for hexadecimal.
|
||||
|
||||
Examples:
|
||||
@ -138,12 +161,11 @@ Examples:
|
||||
0xFE // Hexadecimal literal
|
||||
0xfe // Hexadecimal literal
|
||||
|
||||
Numeric literals represent finite bit sequences (i.e., they have type
|
||||
`[n]`). Using binary, octal, and hexadecimal notation results in bit
|
||||
sequences of a fixed length, depending on the number of digits in the
|
||||
literal. Decimal literals are overloaded, and so the length of the
|
||||
sequence is inferred from context in which the literal is used.
|
||||
Examples:
|
||||
Numeric literals in binary, octal, or hexadecimal notation result in
|
||||
bit sequences of a fixed length (i.e., they have type `[n]` for
|
||||
some `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:
|
||||
|
||||
0b1010 // : [4], 1 * number of digits
|
||||
0o1234 // : [12], 3 * number of digits
|
||||
@ -173,11 +195,11 @@ Operator Associativity Description
|
||||
|
||||
Table: Bit operations.
|
||||
|
||||
If Then Else with Multiway
|
||||
==========================
|
||||
Multi-way Conditionals
|
||||
======================
|
||||
|
||||
`If then else` has been extended to support multi-way
|
||||
conditionals. Examples:
|
||||
The `if ... then ... else` construct can be used with
|
||||
multiple branches. For example:
|
||||
|
||||
x = if y % 2 == 0 then 22 else 33
|
||||
|
||||
@ -189,9 +211,9 @@ conditionals. Examples:
|
||||
Tuples and Records
|
||||
==================
|
||||
|
||||
Tuples and records are used for packaging multiples values together.
|
||||
Tuples are enclosed in parenthesis, while records are enclosed in
|
||||
braces. The components of both tuples and records are separated by
|
||||
Tuples and records are used for packaging multiple values together.
|
||||
Tuples are enclosed in parentheses, while records are enclosed in
|
||||
curly braces. The components of both tuples and records are separated by
|
||||
commas. The components of tuples are expressions, while the
|
||||
components of records are a label and a value separated by an equal
|
||||
sign. Examples:
|
||||
@ -287,7 +309,7 @@ Operator Description
|
||||
|
||||
Table: Sequence operations.
|
||||
|
||||
There are also lifted point-wise operations.
|
||||
There are also lifted pointwise operations.
|
||||
|
||||
[p1, p2, p3, p4] // Sequence pattern
|
||||
p1 # p2 // Split sequence pattern
|
||||
@ -312,7 +334,7 @@ Explicit Type Instantiation
|
||||
|
||||
If `f` is a polymorphic value with type:
|
||||
|
||||
f : { tyParam }
|
||||
f : { tyParam } tyParam
|
||||
f = zero
|
||||
|
||||
you can evaluate `f`, passing it a type parameter:
|
||||
@ -326,13 +348,13 @@ Demoting Numeric Types to Values
|
||||
The value corresponding to a numeric type may be accessed using the
|
||||
following notation:
|
||||
|
||||
`{t}
|
||||
`t
|
||||
|
||||
Here `t` should be a type expression with numeric kind. The resulting
|
||||
expression is a finite word, which is sufficiently large to accommodate
|
||||
the value of the type:
|
||||
|
||||
`{t} : {w >= width t}. [w]
|
||||
`t : {n} (fin n, n >= width t) => [n]
|
||||
|
||||
Explicit Type Annotations
|
||||
=========================
|
||||
@ -418,14 +440,12 @@ Sometimes, we may want to import only some of the definitions
|
||||
from a module. To do so, we use an import declaration with
|
||||
an ***import list***.
|
||||
|
||||
|
||||
module M where
|
||||
module M where
|
||||
|
||||
f = 0x02
|
||||
g = 0x03
|
||||
h = 0x04
|
||||
|
||||
|
||||
module N where
|
||||
|
||||
import M(f,g) // Imports only `f` and `g`, but not `h`
|
||||
@ -473,13 +493,13 @@ Another way to avoid name collisions is by using a
|
||||
f : [8]
|
||||
f = 2
|
||||
|
||||
module N where
|
||||
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`
|
||||
import M as P
|
||||
|
||||
g = P::f
|
||||
// `f` was imported from `M`
|
||||
// but when used it needs to be prefixed by the qualified `P`
|
||||
|
||||
Qualified imports make it possible to work with definitions
|
||||
that happen to have the same name but are defined in different modules.
|
||||
|
BIN
docs/Syntax.pdf
BIN
docs/Syntax.pdf
Binary file not shown.
Loading…
Reference in New Issue
Block a user