Update Syntax.md and re-sync it with Syntax.tex

Note that Syntax.tex should be generated automatically
This commit is contained in:
Iavor Diatchki 2019-02-18 17:20:01 -08:00
parent 1b780c21e1
commit 6a8c6c3134
7 changed files with 303 additions and 241 deletions

Binary file not shown.

View File

@ -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

View 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.

View File

@ -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.

View File

@ -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.

Binary file not shown.