Adds "replPrompt" command

This commit is contained in:
Ben Selfridge 2020-12-11 15:49:06 -08:00
parent 9eb733d74e
commit f45389b8cd
5 changed files with 149 additions and 98 deletions

View File

@ -7,9 +7,9 @@ module Main(main) where
import Control.Monad.State import Control.Monad.State
import Options.Applicative import Options.Applicative
import Data.Char (isSpace) import Data.Char (isSpace, isAlpha)
import Data.Foldable (traverse_) import Data.Foldable (traverse_)
import Data.List (isInfixOf, stripPrefix) import Data.List (isInfixOf, isPrefixOf, stripPrefix)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import qualified Data.Sequence as Seq import qualified Data.Sequence as Seq
import Numeric.Natural import Numeric.Natural
@ -55,47 +55,38 @@ trim = f . f
-- LaTeX processing state monad -- LaTeX processing state monad
-- --
-- We process the text-by-line. The behavior of the state monad on a line is -- We process the text-by-line. The behavior of the state monad on a line is
-- governed by the mode it is currently in. The overall idea is to read in -- governed by the mode it is currently in. The current mode dictates how to
-- "replin" and "replout" sections of the file in alternation, grouping each -- interpret each line, and which mode to transition to next.
-- replin/replout pair into discrete ReplData elements which will be validated
-- against the Cryptol REPL. The current mode dictates how to interpret each
-- line, and which mode to transition to next.
-- --
-- There are four modes: AwaitingReplinMode, ReplinMode, AwaitingReploutMode, -- There are four modes: AwaitingReplMode, ReplinMode, ReploutMode, and
-- and ReploutMode. Below we describe the behavior of each mode. -- ReplPromptMode. Below we describe the behavior of each mode.
-- --
-- AwaitingReplinMode: When in this mode, we are anticipating "replin" lines; -- AwaitingReplMode: When in this mode, we are anticipating "replin" or
-- that is, lines that will be issued as input to the repl. When we see a -- "replout" lines; that is, lines that will be issued as input to the repl or
-- \begin{replinVerb}, we transition to ReplinMode. When we see a -- expected as output from the repl.. When we see a \begin{replinVerb}, we
-- \begin{reploutVerb}, we transition to ReploutMode. When we see an inline -- transition to ReplinMode. When we see a \begin{reploutVerb}, we transition to
-- \replin{..} command, we add the content to the list of replin lines without -- ReploutMode. When we see a \begin{replPromptVerb}, we transition to
-- changing modes. When we see an inline \replout{..} command, we switch to -- ReplPromptMode. When we see an inline \replin{..} command, we add the content
-- AwaitingReploutMode and add the content to the list of replout lines. -- to the list of replin lines without changing modes. When we see an inline
-- \replout{..} command, we add the content to the list of replout lines without
-- changing modes.
-- --
-- ReplinMode: When in this mode, we are inside of a "\begin{replinVerb}" -- ReplinMode: When in this mode, we are inside of a "\begin{replinVerb}"
-- section. When we see a \end{replinVerb} line, we transition to -- section. When we see a \end{replinVerb} line, we transition to
-- AwaitingReplinMode (since there could be more replin lines following some -- AwaitingReplMode. Otherwise, we simply add the entire line to the list of
-- explanatory text). Otherwise, we simply add the entire line to the list of
-- replin lines. -- replin lines.
-- --
-- AwaitingReploutMode: When in this mode, we are anticipating "replout" lines; -- ReploutMode: Like ReplinMode, except we add each line to the expected output.
-- that is, lines that should be compared to the output of the repl once the --
-- already-processed replin lines have been issued to the REPL. When we see a -- ReplPromptMode: A combination of ReplinMode and ReploutMode. Each line is
-- \begin{reploutVerb}, we transition to ReploutMode. When we see a -- either added to input or expected output. If the line starts with a prompt
-- \begin{replinVerb}, we have come to the end of this particular ReplData -- like "Cryptol>" or "Float>", it is added to expected input. Otherwise it is
-- segment, so we package up the replin and replout lines into a ReplData, add -- added to expected output.
-- that new object to the growing list of ReplData objects to be validated, and
-- transition to ReplinMode to start reading in lines for the next ReplData.
-- When we see a \replout{..} command, we add the content to the list of replout
-- lines without changing modes. When we see an inline \replin{..} command, we
-- treat it like a \begin{replinVerb}, except we also add the contents as the
-- first line of replin, and we transition to AwaitingReplinMode rather than
-- ReplinMode.
data PMode = AwaitingReplinMode data PMode = AwaitingReplMode
| ReplinMode | ReplinMode
| AwaitingReploutMode
| ReploutMode | ReploutMode
| ReplPromptMode
deriving (Eq, Show) deriving (Eq, Show)
data Line = Line { lineNum :: Natural data Line = Line { lineNum :: Natural
@ -124,7 +115,7 @@ data PState = PState { pMode :: PMode
deriving (Eq, Show) deriving (Eq, Show)
initPState :: PState initPState :: PState
initPState = PState AwaitingReplinMode Seq.empty Seq.empty Seq.empty 1 initPState = PState AwaitingReplMode Seq.empty Seq.empty Seq.empty 1
-- | P monad for reading in lines -- | P monad for reading in lines
type P = State PState type P = State PState
@ -195,6 +186,11 @@ addReplout s = do
nextLine :: P () nextLine :: P ()
nextLine = modify' $ \st -> st { pCurrentLine = pCurrentLine st + 1 } nextLine = modify' $ \st -> st { pCurrentLine = pCurrentLine st + 1 }
stripPrompt :: String -> Maybe String
stripPrompt s = case span isAlpha s of
(_:_, '>':s') -> Just s'
_ -> Nothing
-- | The main function for our monad. Input is a single line. -- | The main function for our monad. Input is a single line.
processLine :: String -> P () processLine :: String -> P ()
processLine s = do processLine s = do
@ -203,34 +199,33 @@ processLine s = do
m <- gets pMode m <- gets pMode
ln <- gets pCurrentLine ln <- gets pCurrentLine
case m of case m of
AwaitingReplinMode AwaitingReplMode
| "\\begin{replinVerb}" `isInfixOf` s_nowhitespace -> do | "\\begin{replinVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from awaiting to ingesting repl input.
modify' $ \st -> st { pMode = ReplinMode } modify' $ \st -> st { pMode = ReplinMode }
nextLine nextLine
| "\\begin{reploutVerb}" `isInfixOf` s_nowhitespace -> do | "\\begin{reploutVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from awaiting repl input to ingesting repl output.
modify' $ \st -> st { pMode = ReploutMode } modify' $ \st -> st { pMode = ReploutMode }
nextLine nextLine
| "\\begin{replPrompt}" `isInfixOf` s_nowhitespace -> do
modify' $ \st -> st { pMode = ReplPromptMode }
nextLine
| "\\restartrepl" `isInfixOf` s_nowhitespace -> do | "\\restartrepl" `isInfixOf` s_nowhitespace -> do
-- Commit the input with no accompanying output, indicating it should -- This is a command that acts as the barrier between discrete
-- be checked for errors but that the result can be discarded. -- input/output pairs. When we see it, we commit the current pair,
-- begin a brand new pair, and advance to the next line.
addReplData addReplData
nextLine nextLine
| Just (InlineReplin, cmd, rst) <- inlineRepl s -> do | Just (InlineReplin, cmd, rst) <- inlineRepl s -> do
-- Ingest an inline replin command.
addReplin cmd addReplin cmd
processLine rst processLine rst
| Just (InlineReplout, cmd, rst) <- inlineRepl s -> do | Just (InlineReplout, cmd, rst) <- inlineRepl s -> do
-- Ingest an inline replout command, switching to replout mode.
modify' $ \st -> st { pMode = AwaitingReploutMode }
addReplout cmd addReplout cmd
processLine rst processLine rst
| otherwise -> nextLine | otherwise -> nextLine
ReplinMode ReplinMode
| "\\end{replinVerb}" `isInfixOf` s_nowhitespace -> do | "\\end{replinVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from ingesting repl input to awaiting repl input. -- Switching from ingesting repl input to awaiting repl input.
modify' $ \st -> st { pMode = AwaitingReplinMode } modify' $ \st -> st { pMode = AwaitingReplMode }
nextLine nextLine
| otherwise -> do | otherwise -> do
-- Ingest the current line, and stay in ReplinMode. -- Ingest the current line, and stay in ReplinMode.
@ -240,35 +235,10 @@ processLine s = do
-- mode. -- mode.
modify' $ \st -> st { pReplin = replin' } modify' $ \st -> st { pReplin = replin' }
nextLine nextLine
AwaitingReploutMode
| "\\begin{reploutVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from awaiting to ingesting repl output.
modify' $ \st -> st { pMode = ReploutMode }
nextLine
| "\\begin{replinVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from awaiting repl output to ingesting repl input. This
-- indicates we have finished building the current repl data, so
-- commit it by appending it to the end of the list of completed repl
-- data and start a fresh one.
addReplData
modify' $ \st -> st { pMode = ReplinMode }
nextLine
| Just (InlineReplin, cmd, rst) <- inlineRepl s -> do
-- Ingest an inline replin command, switching to replin mode and
-- committing the current repl data.
addReplData
modify' $ \st -> st { pMode = AwaitingReplinMode }
addReplin cmd
processLine rst
| Just (InlineReplout, cmd, rst) <- inlineRepl s -> do
-- Ingest an replout command.
addReplout cmd
processLine rst
| otherwise -> nextLine
ReploutMode ReploutMode
| "\\end{reploutVerb}" `isInfixOf` s_nowhitespace -> do | "\\end{reploutVerb}" `isInfixOf` s_nowhitespace -> do
-- Switching from ingesting repl output to awaiting repl output. -- Switching from ingesting repl output to awaiting repl output.
modify' $ \st -> st { pMode = AwaitingReploutMode } modify' $ \st -> st { pMode = AwaitingReplMode }
nextLine nextLine
| otherwise -> do | otherwise -> do
-- Ingest the current line, and stay in ReploutMode. -- Ingest the current line, and stay in ReploutMode.
@ -278,6 +248,27 @@ processLine s = do
-- mode. -- mode.
modify' $ \st -> st { pReplout = replout' } modify' $ \st -> st { pReplout = replout' }
nextLine nextLine
ReplPromptMode
| "\\end{replPrompt}" `isInfixOf` s_nowhitespace -> do
-- Switching from ingesting repl input/output to awaiting repl
-- input.
modify' $ \st -> st { pMode = AwaitingReplMode }
nextLine
| Just input <- stripPrompt (trim s) -> do
replin <- gets pReplin
let input' = trim input
replin' = replin Seq.|> Line ln input' -- use the full input since
-- % isn't a comment in
-- verbatim mode.
modify $ \st -> st { pReplin = replin' }
nextLine
| otherwise -> do
replout <- gets pReplout
let replout' = replout Seq.|> Line ln s -- use the full input since %
-- isn't a comment in verbatim
-- mode.
modify $ \st -> st { pReplout = replout' }
nextLine
main :: IO () main :: IO ()
main = do main = do
@ -327,7 +318,7 @@ main = do
-- remove temporary input file -- remove temporary input file
removeFile inFile removeFile inFile
let outText = unlines $ filter (not . null) $ trim <$> (tail $ lines cryOut) let outText = unlines $ filter (not . null) $ trim <$> (dropWhile ("Loading module" `isPrefixOf`) $ lines cryOut)
writeFile outFile outText writeFile outFile outText

Binary file not shown.

View File

@ -56,7 +56,6 @@ word. We can also supply partial types. For example,
\begin{replinVerb} \begin{replinVerb}
12 : [_] 12 : [_]
\end{replinVerb} \end{replinVerb}
\restartrepl
means that \texttt{12} has a word type with an unspecified number of 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 bits. Cryptol will infer the unspecified part of the type in this
case. We shall see many other examples of typed expressions in the case. We shall see many other examples of typed expressions in the
@ -79,6 +78,7 @@ that act on bit values.
\begin{Exercise}\label{ex:dataBit} \begin{Exercise}\label{ex:dataBit}
Type in the following expressions at the Cryptol prompt, and observe Type in the following expressions at the Cryptol prompt, and observe
the output: the output:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
True True
false false
@ -129,6 +129,7 @@ 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 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 to set the output base to be 10 while working on the following
example. To do so, use the command:\indSettingBase example. To do so, use the command:\indSettingBase
\restartrepl
\begin{replinVerb} \begin{replinVerb}
:set base=10 :set base=10
\end{replinVerb} \end{replinVerb}
@ -177,6 +178,7 @@ override this by giving an explicit type signature.\indSignature
%% keep track of how many bits they need, so the current behavior was %% keep track of how many bits they need, so the current behavior was
%% deemed a good compromise. %% deemed a good compromise.
\restartrepl
\begin{Exercise}\label{ex:decimalType} \begin{Exercise}\label{ex:decimalType}
Try writing some decimal numbers at different types, like Try writing some decimal numbers at different types, like
\texttt{12:[4]} and \texttt{50:[8]}. How does Cryptol respond if \texttt{12:[4]} and \texttt{50:[8]}. How does Cryptol respond if
@ -201,6 +203,7 @@ override this by giving an explicit type signature.\indSignature
the smallest type for \texttt{0}. the smallest type for \texttt{0}.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:setBase} \begin{Exercise}\label{ex:setBase}
Experiment with different output bases by issuing {\tt :set Experiment with different output bases by issuing {\tt :set
base=10}, and other base values. Also try writing numbers directly base=10}, and other base values. Also try writing numbers directly
@ -232,6 +235,7 @@ represents the integer 255. To write a negative integer, simply negate
the result: For example, \texttt{-12} and \texttt{- toInteger 0xc} the result: For example, \texttt{-12} and \texttt{- toInteger 0xc}
represent the integer $-12$. represent the integer $-12$.
\restartrepl
\begin{Exercise}\label{ex:int:1} \begin{Exercise}\label{ex:int:1}
Compare the results of evaluating the expressions \replin|0x8 + 0x9| Compare the results of evaluating the expressions \replin|0x8 + 0x9|
and \replin|toInteger 0x8 + toInteger 0x9|. Also try evaluating and \replin|toInteger 0x8 + toInteger 0x9|. Also try evaluating
@ -258,6 +262,7 @@ positive \texttt{n}. \texttt{Z n} represents the ring of integers modulo \textt
Just like with fixed-width bitvector values, arithmetic in Just like with fixed-width bitvector values, arithmetic in
\texttt{Z n} will ``wrap around'' (i.e., be reduced modulo \texttt{n}) \texttt{Z n} will ``wrap around'' (i.e., be reduced modulo \texttt{n})
when values get too large. when values get too large.
\restartrepl
\begin{Exercise}\label{ex:int:2} \begin{Exercise}\label{ex:int:2}
Compare the results of evaluating \replin| (5 : Z 7) + (6 : Z 7) | Compare the results of evaluating \replin| (5 : Z 7) + (6 : Z 7) |
with \replin| fromZ (5 : Z 7) + fromZ (6 : Z 7) |. with \replin| fromZ (5 : Z 7) + fromZ (6 : Z 7) |.
@ -283,6 +288,7 @@ implement the \texttt{Field} operations for \texttt{Z p}.
The type \texttt{Z p} is also known as the The type \texttt{Z p} is also known as the
``prime field of characteristic \texttt{p}'' when \texttt{p} is prime. ``prime field of characteristic \texttt{p}'' when \texttt{p} is prime.
\restartrepl
\begin{Exercise}\label{ex:int:3} \begin{Exercise}\label{ex:int:3}
What are the results of evaluating the following expressions? What are the results of evaluating the following expressions?
\begin{replinVerb} \begin{replinVerb}
@ -331,6 +337,7 @@ in decimal, hex and binary forms, as well as using scientific notation.
For example, all of the following expression create the same For example, all of the following expression create the same
value representing one half: value representing one half:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
ratio 1 2 ratio 1 2
ratio 2 4 ratio 2 4
@ -383,7 +390,9 @@ Of particular importance is the relation \texttt{=.=} for comparing
floating point numbers semantically, rather that using the IEEE equality, floating point numbers semantically, rather that using the IEEE equality,
which is done by \texttt{==}. The behavior of the two differs which is done by \texttt{==}. The behavior of the two differs
mostly on special values, here are some examples: mostly on special values, here are some examples:
\begin{Verbatim} \restartrepl
\hidereplin|:m Float|
\begin{replPrompt}
Float> fpNaN == (fpNaN : Float64) Float> fpNaN == (fpNaN : Float64)
False False
Float> fpNaN =.= (fpNaN : Float64) Float> fpNaN =.= (fpNaN : Float64)
@ -392,7 +401,7 @@ Float> 0 == (-0 : Float64)
True True
Float> 0 =.= (-0 : Float64) Float> 0 =.= (-0 : Float64)
False False
\end{Verbatim} \end{replPrompt}
\restartrepl \restartrepl
Cryptol supports reasoning about floating point numbers using the Cryptol supports reasoning about floating point numbers using the
@ -430,6 +439,7 @@ of type \texttt{()}.
\begin{Exercise}\label{ex:tup:1} \begin{Exercise}\label{ex:tup:1}
Try out the following tuples: Try out the following tuples:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
(1, 2+4) : (Integer, Integer) (1, 2+4) : (Integer, Integer)
(True, False, True ^ False) (True, False, True ^ False)
@ -458,6 +468,7 @@ empty tuple, as it has no components to project.
\begin{Exercise}\label{ex:tup:2} \begin{Exercise}\label{ex:tup:2}
Try out the following examples: Try out the following examples:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
(1, 2+4).0 : Integer (1, 2+4).0 : Integer
(1, 2+4).1 : Integer (1, 2+4).1 : Integer
@ -506,6 +517,7 @@ comma-separated elements.\indTheSequenceType
\begin{Exercise}\label{ex:seq:1} \begin{Exercise}\label{ex:seq:1}
Try out the following sequences: Try out the following sequences:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
[1, 2] [1, 2]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
@ -523,6 +535,7 @@ $3\times3$ matrix.
\begin{Exercise}\label{ex:seq:2} \begin{Exercise}\label{ex:seq:2}
Type in the following expressions to Cryptol and observe the Type in the following expressions to Cryptol and observe the
type errors: type errors:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
[True, [True]] [True, [True]]
[[1, 2, 3], [4, 5]] [[1, 2, 3], [4, 5]]
@ -563,6 +576,7 @@ constructs guarantee that enumeration elements are distinct.
\begin{Exercise}\label{ex:seq:3} \begin{Exercise}\label{ex:seq:3}
Explore various ways of constructing enumerations in Cryptol, by Explore various ways of constructing enumerations in Cryptol, by
using the following expressions: using the following expressions:
\restartrepl
\begin{replinVerb} \begin{replinVerb}
[1 .. 10 : Integer] // increment with step 1 [1 .. 10 : Integer] // increment with step 1
[1, 3 .. 10 : Integer] // increment with step 2 (= 3-1) [1, 3 .. 10 : Integer] // increment with step 2 (= 3-1)
@ -604,6 +618,7 @@ comprehensions are not generalized numeric comprehensions (like
summation, product, maximum, or minimum), though such comprehensions summation, product, maximum, or minimum), though such comprehensions
can certainly be defined using Cryptol comprehensions. can certainly be defined using Cryptol comprehensions.
\restartrepl
\begin{Exercise}\label{ex:seq:4} \begin{Exercise}\label{ex:seq:4}
The components of a Cryptol sequence comprehension are an expression The components of a Cryptol sequence comprehension are an expression
of one or more variables (which defines each element of the of one or more variables (which defines each element of the
@ -636,6 +651,7 @@ multiplied. For instance, in the first example, the generator
$2\times 3 = 6$ elements. $2\times 3 = 6$ elements.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:seq:5}\indParallel\indComp \begin{Exercise}\label{ex:seq:5}\indParallel\indComp
A comprehension with multiple branches is called a \emph{parallel A comprehension with multiple branches is called a \emph{parallel
comprehension}. We can have any number of parallel branches. The comprehension}. We can have any number of parallel branches. The
@ -738,6 +754,7 @@ them very useful for permuting sequences).
\todo[inline]{Cite other languages that express permutations like this?} \todo[inline]{Cite other languages that express permutations like this?}
\restartrepl
\begin{Exercise}\label{ex:seq:7} \begin{Exercise}\label{ex:seq:7}
Try out the following Cryptol expressions: Try out the following Cryptol expressions:
\begin{replinVerb} \begin{replinVerb}
@ -786,6 +803,7 @@ Here are Cryptol's responses:
\end{reploutVerb} \end{reploutVerb}
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:seq:8} \begin{Exercise}\label{ex:seq:8}
The permutation operators ({\tt @@} and {\tt !!}) can be defined The permutation operators ({\tt @@} and {\tt !!}) can be defined
using sequence comprehensions. Write an expression that selects the using sequence comprehensions. Write an expression that selects the
@ -801,7 +819,6 @@ Using a comprehension, we can express the same idea using:
\begin{replinVerb} \begin{replinVerb}
[ [0 .. 10] @ i | i <- [0, 2 .. 10] ] [ [0 .. 10] @ i | i <- [0, 2 .. 10] ]
\end{replinVerb} \end{replinVerb}
\restartrepl
Strictly speaking, permutation operations are indeed redundant. Strictly speaking, permutation operations are indeed redundant.
However, they lead to more concise and easier-to-read expressions. However, they lead to more concise and easier-to-read expressions.
\end{Answer} \end{Answer}
@ -818,6 +835,7 @@ elements are accessed \emph{on demand}. This implies that Cryptol will
infinite sequence: it will lazily construct the sequence and make its infinite sequence: it will lazily construct the sequence and make its
elements available as demanded by the program. elements available as demanded by the program.
\restartrepl
\begin{Exercise}\label{ex:seq:9} \begin{Exercise}\label{ex:seq:9}
Try the following infinite enumerations:\hidereplin|:set base=10| Try the following infinite enumerations:\hidereplin|:set base=10|
\begin{replinVerb} \begin{replinVerb}
@ -846,18 +864,24 @@ Try the following infinite enumerations:\hidereplin|:set base=10|
\note{We are explicitly telling Cryptol to use 32-bit words \note{We are explicitly telling Cryptol to use 32-bit words
as the elements. The reason for doing so will become clear when we as the elements. The reason for doing so will become clear when we
study arithmetic shortly.} study arithmetic shortly.}
\restartrepl
\begin{Exercise}\label{ex:seq:10} \begin{Exercise}\label{ex:seq:10}
What happens if you use the reverse index operator ({\tt !}) on an What happens if you use the reverse index operator ({\tt !}) on an
infinite sequence? Why? infinite sequence? Why?
\end{Exercise} \end{Exercise}
\begin{Answer}\ansref{ex:seq:10} \begin{Answer}\ansref{ex:seq:10}
Here is a simple test case: Here is a simple test case:
\begin{Verbatim} \begin{replPrompt}
Cryptol> [1:[32] ...] ! 3 Cryptol> [1:[32] ...] ! 3
[error] at <interactive>:1:1--1:17: [error] at <interactive>:1:1--1:17:
Expected a finite type, but found `inf`. • Unsolvable constraint:
\end{Verbatim} fin inf
arising from
use of expression (!)
at <interactive>:1:1--1:17
\end{replPrompt}
The error message is telling us that we \emph{cannot} apply the reverse The error message is telling us that we \emph{cannot} apply the reverse
index operator ({\tt !}) on an infinite sequence (\texttt{inf}). This index operator ({\tt !}) on an infinite sequence (\texttt{inf}). This
is a natural consequence of the fact that one can never reach the end is a natural consequence of the fact that one can never reach the end
@ -876,6 +900,7 @@ built-in functions for manipulating them in various ways. It is
worthwhile to try the following exercises to gain basic familiarity worthwhile to try the following exercises to gain basic familiarity
with the basic operations. with the basic operations.
\restartrepl
\begin{Exercise}\label{ex:seq:11} \begin{Exercise}\label{ex:seq:11}
Try the following expressions:\indTake\indDrop\indSplit\indGroup\indJoin\indTranspose Try the following expressions:\indTake\indDrop\indSplit\indGroup\indJoin\indTranspose
\begin{replinVerb} \begin{replinVerb}
@ -977,24 +1002,28 @@ 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 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 given as arguments, but are determined by the type of the argument
sequence and the result context. sequence and the result context.
\begin{Verbatim} \restartrepl
\hidereplin|:set base=10|
\begin{replPrompt}
Cryptol> split [1..12] : [1][12][8] Cryptol> split [1..12] : [1][12][8]
[[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> split [1..12] : [2][6][8] Cryptol> split [1..12] : [2][6][8]
[[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> split [1..12] : [3][4][8] Cryptol> split [1..12] : [3][4][8]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
\end{Verbatim} \end{replPrompt}
Here is what happens if we do {\em not} give an explicit signature on Here is what happens if we do {\em not} give an explicit signature on
the result:\indSignature the result:\indSignature
\begin{Verbatim} \restartrepl
\hidereplin|:set base=10|
\begin{replPrompt}
Cryptol> split [1..12] Cryptol> split [1..12]
Cannot evaluate polymorphic value. Cannot evaluate polymorphic value.
Type: {n, m, a} (n * m == 12, Literal 12 a, fin m) => [n][m]a Type: {n, m, a} (n * m == 12, Literal 12 a, fin m) => [n][m]a
Cryptol> :t split [1..12] Cryptol> :t split [1..12]
split [1 .. 12] : {n, m, a} (n * m == 12, Literal 12 a, fin m) => split [1 .. 12] : {n, m, a} (n * m == 12, Literal 12 a, fin m) =>
[n][m]a [n][m]a
\end{Verbatim} \end{replPrompt}
%% cryptol 1 said: : {a b c} (fin c,c >= 4,a*b == 12) => [a][b][c] %% 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 A complex type signature like this one first defines a set of type
@ -1012,6 +1041,7 @@ very powerful function. The flexibility afforded by \texttt{split}
comes in very handy in Cryptol. We shall see one example of its usage comes in very handy in Cryptol. We shall see one example of its usage
later in \autoref{sec:scytale}. later in \autoref{sec:scytale}.
\restartrepl
\begin{Exercise}\label{ex:split:0} \begin{Exercise}\label{ex:split:0}
With a sequence of length 12, as in the above example, there are 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 precisely 6 ways of splitting it: 1 $\times$ 12, 2 $\times$ 6, 3
@ -1020,30 +1050,33 @@ later in \autoref{sec:scytale}.
corresponding to the latter three.\indSplit corresponding to the latter three.\indSplit
\end{Exercise} \end{Exercise}
\begin{Answer}\ansref{ex:split:0} \begin{Answer}\ansref{ex:split:0}
Here they are:\indSplit Here they are:\indSplit
\begin{Verbatim} \hidereplin|:set base=10|
\begin{replPrompt}
Cryptol> split [1..12] : [4][3][8] Cryptol> split [1..12] : [4][3][8]
[[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> split [1..12] : [6][2][8] Cryptol> split [1..12] : [6][2][8]
[[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> split [1..12] : [12][1][8] Cryptol> split [1..12] : [12][1][8]
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]] [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]]
\end{Verbatim} \end{replPrompt}
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:split:1} \begin{Exercise}\label{ex:split:1}
What happens when you type What happens when you type
\texttt{split [1 ..\ 12] :\ [5][2][8]}?\indSplit \texttt{split [1 ..\ 12] :\ [5][2][8]}?\indSplit
\end{Exercise} \end{Exercise}
\begin{Answer}\ansref{ex:split:1} \begin{Answer}\ansref{ex:split:1}
Cryptol will issue a type error:\indSplit Cryptol will issue a type error:\indSplit
\begin{Verbatim} \begin{replPrompt}
Cryptol> split [1..12] : [5][2][8] Cryptol> split [1..12] : [5][2][8]
[error] at <interactive>:1:7--1:14: [error] at <interactive>:1:7--1:14:
Type mismatch: Type mismatch:
Expected type: 10 Expected type: 10
Inferred type: 12 Inferred type: 12
\end{Verbatim} When checking type of function argument
\end{replPrompt}
Cryptol is telling us that we have requested 10 elements in the final Cryptol is telling us that we have requested 10 elements in the final
result (5 $\times$ 2), but the input has 12. result (5 $\times$ 2), but the input has 12.
\end{Answer} \end{Answer}
@ -1078,6 +1111,7 @@ lines.)\indLineCont \todo[inline]{You don't need nested
Common operations on sequences include shifting and rotating them. Common operations on sequences include shifting and rotating them.
Cryptol supports both versions with left/right Cryptol supports both versions with left/right
variants.\indShiftLeft\indShiftRight\indRotLeft\indRotRight variants.\indShiftLeft\indShiftRight\indRotLeft\indRotRight
\restartrepl
\begin{Exercise}\label{ex:seq:14} \begin{Exercise}\label{ex:seq:14}
Experiment with the following expressions: Experiment with the following expressions:
\begin{replinVerb} \begin{replinVerb}
@ -1144,6 +1178,7 @@ abbreviation for \texttt{[6]Bit}.
$$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$$ $$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} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:words:1} \begin{Exercise}\label{ex:words:1}
Try out the following words: \lhint{It might help to use \replin|:set base=2| Try out the following words: \lhint{It might help to use \replin|:set base=2|
to see the bit patterns.}\indSettingBase to see the bit patterns.}\indSettingBase
@ -1173,6 +1208,7 @@ $$1\times2^5 + 0\times2^4 + 1\times2^3 + 0\times2^2 + 1\times2^1 + 0\times2^0 =
\end{reploutVerb} \end{reploutVerb}
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:words:4} \begin{Exercise}\label{ex:words:4}
Since words are sequences, the sequence functions from Since words are sequences, the sequence functions from
\exerciseref{ex:seq:11} apply to words as well. \exerciseref{ex:seq:11} apply to words as well.
@ -1256,6 +1292,7 @@ numbers.\footnote{This is a significant change from Cryptol version 1,
matches the traditional matches the traditional
interpretation.}\indRotLeft\indRotRight\indShiftLeft\indShiftRight interpretation.}\indRotLeft\indRotRight\indShiftLeft\indShiftRight
\restartrepl
\begin{Exercise}\label{ex:words:6} \begin{Exercise}\label{ex:words:6}
Try the following examples of shifting/rotating words: Try the following examples of shifting/rotating words:
\begin{replinVerb} \begin{replinVerb}
@ -1342,6 +1379,7 @@ equal if they have the same number of fields, if their field names are
identical, if identically named fields are of comparable types and identical, if identically named fields are of comparable types and
have equal values. have equal values.
\restartrepl
\begin{Exercise}\label{ex:record:1} \begin{Exercise}\label{ex:record:1}
Type in the following expressions and observe the output: Type in the following expressions and observe the output:
\hidereplin|:set ascii=on| \hidereplin|:set ascii=on|
@ -1422,6 +1460,7 @@ consist of all {\tt True}\indTrue bits:
{xCoord=4095, yCoord=31} {xCoord=4095, yCoord=31}
\end{Verbatim} \end{Verbatim}
\restartrepl
\begin{Exercise}\label{ex:zero:0} \begin{Exercise}\label{ex:zero:0}
We said that {\tt zero} inhabits all types in Cryptol. This also We said that {\tt zero} inhabits all types in Cryptol. This also
includes functions. What do you think the appropriate {\tt zero} includes functions. What do you think the appropriate {\tt zero}
@ -1461,6 +1500,7 @@ resulting word size. While this is very handy for most applications of
Cryptol, it requires some care if overflow has to be treated Cryptol, it requires some care if overflow has to be treated
explicitly.\indOverflow\indUnderflow\indPlus\indMinus\indTimes\indDiv\indMod\indLg\indMin\indMax\indExponentiate explicitly.\indOverflow\indUnderflow\indPlus\indMinus\indTimes\indDiv\indMod\indLg\indMin\indMax\indExponentiate
\restartrepl
\begin{Exercise}\label{ex:arith:1} \begin{Exercise}\label{ex:arith:1}
What is the value of \replin|1 + 1 : [_]|? Surprised? What is the value of \replin|1 + 1 : [_]|? Surprised?
\end{Exercise} \end{Exercise}
@ -1473,6 +1513,7 @@ What is the value of \replin|1 + 1 : [_]|? Surprised?
\hidereplout|* Using '1' for type wildcard (_)| \hidereplout|* Using '1' for type wildcard (_)|
\hidereplout|0x0| \hidereplout|0x0|
\restartrepl
\begin{Exercise}\label{ex:arith:2} \begin{Exercise}\label{ex:arith:2}
What is the value of \replin|1 + 1 : [8]|? Why? What is the value of \replin|1 + 1 : [8]|? Why?
\end{Exercise} \end{Exercise}
@ -1482,6 +1523,7 @@ What is the value of \replin|1 + 1 : [8]|? Why?
sum that is at least 256. sum that is at least 256.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:3} \begin{Exercise}\label{ex:arith:3}
What is the value of \replin|3 - 5 : [_]|? How about \replin|3 - 5 : [8]|? What is the value of \replin|3 - 5 : [_]|? How about \replin|3 - 5 : [8]|?
\end{Exercise} \end{Exercise}
@ -1503,6 +1545,7 @@ What is the value of \replin|3 - 5 : [_]|? How about \replin|3 - 5 : [8]|?
For instance, \texttt{-5} precisely means \texttt{0-5}, and is subject to the For instance, \texttt{-5} precisely means \texttt{0-5}, and is subject to the
usual modular arithmetic rules.}\indModular\indMinus usual modular arithmetic rules.}\indModular\indMinus
\restartrepl
\begin{Exercise}\label{ex:arith:4} \begin{Exercise}\label{ex:arith:4}
Try out the following expressions:\indEq\indNeq Try out the following expressions:\indEq\indNeq
\begin{replinVerb} \begin{replinVerb}
@ -1541,6 +1584,7 @@ operation?
\emph{ceiling log base 2} function.\indLg\indEq\indNeq \emph{ceiling log base 2} function.\indLg\indEq\indNeq
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:5:1} \begin{Exercise}\label{ex:arith:5:1}
Integral division truncates down. Try out the following expressions:\indDiv\indMod Integral division truncates down. Try out the following expressions:\indDiv\indMod
\begin{replinVerb} \begin{replinVerb}
@ -1566,6 +1610,7 @@ $$
whenever $y \neq 0$. whenever $y \neq 0$.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:5} \begin{Exercise}\label{ex:arith:5}
What is the value of \replin|min (5:[_]) (-2)|? Why? What is the value of \replin|min (5:[_]) (-2)|? Why?
Why are the parentheses around \Verb|-2| Why are the parentheses around \Verb|-2|
@ -1584,6 +1629,7 @@ whenever $y \neq 0$.
the expressions \texttt{min 5 - 2} and \texttt{min 5 -2}. the expressions \texttt{min 5 - 2} and \texttt{min 5 -2}.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:6} \begin{Exercise}\label{ex:arith:6}
\hidereplin|:set base=10| \hidereplin|:set base=10|
How about \replin|max 5 (-2:[8])|? Why?\indMin\indModular\indUnaryMinus How about \replin|max 5 (-2:[8])|? Why?\indMin\indModular\indUnaryMinus
@ -1593,6 +1639,7 @@ How about \replin|max 5 (-2:[8])|? Why?\indMin\indModular\indUnaryMinus
-2} is equivalent to {\tt 254}. Therefore the result is \replout|254|. -2} is equivalent to {\tt 254}. Therefore the result is \replout|254|.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:7} \begin{Exercise}\label{ex:arith:7}
Write an expression that computes the sum of two sequences Write an expression that computes the sum of two sequences
\texttt{[1..\ 10]} and \texttt{[10, 9 ..\ 1]}.\indPlus \texttt{[1..\ 10]} and \texttt{[10, 9 ..\ 1]}.\indPlus
@ -1621,6 +1668,7 @@ upon Cryptol's automatic lifting.\indArithLift
operators {\tt ==}, {\tt !=}, {\tt >}, {\tt >=}, {\tt <}, {\tt <=}, operators {\tt ==}, {\tt !=}, {\tt >}, {\tt >=}, {\tt <}, {\tt <=},
with their usual meanings.\indEq\indNeq\indGt\indGte\indLt\indLte with their usual meanings.\indEq\indNeq\indGt\indGte\indLt\indLte
\restartrepl
\begin{Exercise}\label{ex:arith:8} \begin{Exercise}\label{ex:arith:8}
Try out the following expressions: Try out the following expressions:
\begin{replinVerb} \begin{replinVerb}
@ -1640,6 +1688,7 @@ True
\exerciseref{ex:seq:9}, we wrote the infinite \exerciseref{ex:seq:9}, we wrote the infinite
enumeration{\indEnum\indInfSeq}starting at {\tt 1} using an explicit enumeration{\indEnum\indInfSeq}starting at {\tt 1} using an explicit
type as follows: type as follows:
\restartrepl
\hidereplin|:set base=10| \hidereplin|:set base=10|
\begin{replinVerb} \begin{replinVerb}
[(1:[32]) ...] [(1:[32]) ...]
@ -1686,6 +1735,7 @@ will be treated as if the user has written:
and type inference will assign the smallest bit-size possible to and type inference will assign the smallest bit-size possible to
represent {\tt k}. represent {\tt k}.
\restartrepl
\begin{Exercise}\label{ex:arith:9} \begin{Exercise}\label{ex:arith:9}
\hidereplin|:set base=10| \hidereplin|:set base=10|
Remember from \exerciseref{ex:decimalType} that the word \texttt{0} Remember from \exerciseref{ex:decimalType} that the word \texttt{0}
@ -1709,6 +1759,7 @@ element type is \texttt{[0]}. This is one case where \texttt{[k...]}
is subtly different from \texttt{[k, k+1...]}. is subtly different from \texttt{[k, k+1...]}.
\end{Answer} \end{Answer}
\restartrepl
\begin{Exercise}\label{ex:arith:10} \begin{Exercise}\label{ex:arith:10}
What is the value of \replin|[1:Integer .. 10]|? Explain in terms of the above What is the value of \replin|[1:Integer .. 10]|? Explain in terms of the above
discussion on modular arithmetic.\indModular discussion on modular arithmetic.\indModular

View File

@ -73,13 +73,14 @@
\DefineVerbatimEnvironment \DefineVerbatimEnvironment
{reploutVerb}{Verbatim} {reploutVerb}{Verbatim}
{} {}
\DefineVerbatimEnvironment
{replPrompt}{Verbatim}
{}
\CustomVerbatimCommand{\replin}{Verb}{} \CustomVerbatimCommand{\replin}{Verb}{}
\CustomVerbatimCommand{\replout}{Verb}{} \CustomVerbatimCommand{\replout}{Verb}{}
\NewDocumentCommand{\hidereplin}{r||}{} \NewDocumentCommand{\hidereplin}{r||}{}
\NewDocumentCommand{\hidereplout}{r||}{} \NewDocumentCommand{\hidereplout}{r||}{}
\newcommand{\restartrepl}[0]{}{} \newcommand{\restartrepl}[0]{}{}
%% \newcommand{\hidereplin}[1]{}
%% \newcommand{\hidereplout}[1]{}
% \newcommand{\todo}[1]{\begin{center}\framebox{\begin{minipage}{0.8\textwidth}{{\bf TODO:} #1}\end{minipage}}\end{center}} % \newcommand{\todo}[1]{\begin{center}\framebox{\begin{minipage}{0.8\textwidth}{{\bf TODO:} #1}\end{minipage}}\end{center}}
\newcommand{\lamex}{\ensuremath{\lambda}-expression\indLamExp} \newcommand{\lamex}{\ensuremath{\lambda}-expression\indLamExp}

View File

@ -30,17 +30,20 @@ following commands:
This is the markup equivalent of the `Verbatim` environment. This is the markup equivalent of the `Verbatim` environment.
However, it has the added effect of adding every line of the block However, it has the added effect of adding every line of the block
to the expected output of the preceding `\replin` commands. If we add to the expected output of the preceding `\replin` commands.
a `replinVerb` environment or inline `\replin` command after a
`reploutVerb` environment, it has the effect of "completing" the
previous input/output pair to issue to the repl. See CrashCourse.tex
for examples.
* \replout|...|` * \replout|...|`
Inline equivalent of `reploutVerb` environment. Markup equivalent of Inline equivalent of `reploutVerb` environment. Markup equivalent of
`\Verb|...|`. `\Verb|...|`.
* `\begin{replPrompt}` and `\end{replPrompt}`
This is the markup equivalent of the `Verbatim` environment. However, it has
the added effect of adding every line of the block either to input or expected
output. If the line starts with the `Cryptol` prompt, it is added to input;
otherwise, it is added to output.
* `\hidereplout|..|` * `\hidereplout|..|`
Like `\replout|...|`, but is not rendered at all by LaTeX. This is Like `\replout|...|`, but is not rendered at all by LaTeX. This is
@ -49,11 +52,14 @@ following commands:
* `\restartrepl` * `\restartrepl`
This has the effect of terminating the previous input/output REPL This has the effect of terminating the current input/output REPL pair. If
pair without having to include a `reploutVerb` environment or there is input but no output, then instead of checking the output, the tool
`\replout` command. When we don't record any expected output, the checks that the input does not raise an error.
actual REPL output is not checked, but is instead simply issued to
the REPL to ensure no errors are raised. This command is used to divide the REPL input/output pairs into distinct
"blocks" that get submitted to the REPL independently. Therefore, this command
should be called every time we are defining a new REPL pair; in particular, it
should come before every exercise that uses REPL commands.
Other notes: Other notes:
@ -61,3 +67,5 @@ Other notes:
work as expected in all cases (particularly with the inline commands). It's work as expected in all cases (particularly with the inline commands). It's
probably best to avoid using LaTeX comments that are on the same line as any probably best to avoid using LaTeX comments that are on the same line as any
of the above commands. of the above commands.
* Lines starting with "Loading module" are silently ignored from the output.