cws/cw05.tex
changeset 336 25d9c3b2bc99
parent 325 ca9c1cf929fa
child 337 c0d9e6548b08
equal deleted inserted replaced
335:7e00d2b13b04 336:25d9c3b2bc99
    15 
    15 
    16 \begin{document}
    16 \begin{document}
    17 
    17 
    18 \section*{Part 10 (Scala)}
    18 \section*{Part 10 (Scala)}
    19 
    19 
    20 \mbox{}\hfill\textit{``If there's one feature that makes Scala,}\\
    20 \mbox{}\hfill\textit{``If there's one feature that makes Scala, `Scala',}\\
    21 \mbox{}\hfill\textit{`Scala', I would pick implicits.''}\smallskip\\
    21 \mbox{}\hfill\textit{ I would pick implicits.''}\smallskip\\
    22 \mbox{}\hfill\textit{ --- Martin Odersky (creator of the Scala language)}\bigskip\medskip
    22 \mbox{}\hfill\textit{ --- Martin Odersky (creator of the Scala language)}\bigskip\bigskip
    23 
    23 
    24 
    24 
    25 \noindent
    25 \noindent
    26 This part is about a small programming
    26 This part is about a small (esotheric) programming language called
    27 language called brainf***. The part is worth 10\% and you need to 
    27 brainf***. Actually, we will implement an interpreter for our own version
    28 submit on \cwTEN{} at 4pm.\bigskip
    28 of this language called brainf*ck++.\bigskip
    29 
    29 
    30 \IMPORTANT{}
    30 \IMPORTANT{This part is worth 10\% and you need to submit on \cwTEN{} at 4pm.}
    31 
    31 
    32 \noindent
    32 \noindent
    33 Also note that the running time of each part will be restricted to a
    33 Also note that the running time of each part will be restricted to a
    34 maximum of 30 seconds on my laptop.
    34 maximum of 30 seconds on my laptop.
    35 
    35 
    92 Coming from Java or C++, you might think Scala is a rather esoteric
    92 Coming from Java or C++, you might think Scala is a rather esoteric
    93 programming language.  But remember, some serious companies have built
    93 programming language.  But remember, some serious companies have built
    94 their business on
    94 their business on
    95 Scala.\footnote{\url{https://en.wikipedia.org/wiki/Scala_(programming_language)\#Companies}}
    95 Scala.\footnote{\url{https://en.wikipedia.org/wiki/Scala_(programming_language)\#Companies}}
    96 I claim functional programming is not a fad.  And there are far, far
    96 I claim functional programming is not a fad.  And there are far, far
    97 more esoteric languages out there. One is called \emph{brainf***}. You
    97 more esoteric languages out there. One is called \emph{brainf***}. 
       
    98 \here{https://esolangs.org/wiki/Brainfuck}
       
    99 You
    98 are asked in this part to implement an interpreter for
   100 are asked in this part to implement an interpreter for
    99 this language.
   101 a slight extension of this language.
   100 
   102 
   101 Urban M\"uller developed brainf*** in 1993.  A close relative of this
   103 Urban M\"uller developed the original version of brainf*** in 1993.  A close
   102 language was already introduced in 1964 by Corado B\"ohm, an Italian
   104 relative of this language was already introduced in 1964 by Corado
   103 computer pioneer. The main feature of brainf*** is its minimalistic
   105 B\"ohm, an Italian computer pioneer. The main feature of brainf*** is
   104 set of instructions---just 8 instructions in total and all of which
   106 its minimalistic set of instructions---just 8 instructions in total
   105 are single characters. Despite the minimalism, this language has been
   107 and all of which are single characters. Despite the minimalism, this
   106 shown to be Turing complete\ldots{}if this doesn't ring any bell with
   108 language has been shown to be Turing complete\ldots{}if this doesn't
   107 you: it roughly means that every(!) algorithm can, in principle,
   109 ring any bell with you: it roughly means that every(!) algorithm can,
   108 be implemented in brainf***. It just takes a lot of determination and
   110 in principle, be implemented in brainf***. It just takes a lot of
   109 quite a lot of memory resources. Some relatively sophisticated sample
   111 determination and quite a lot of memory resources.
   110 programs in brainf*** are given in the file \texttt{bf.scala}, including
   112 
   111 a brainf*** program for the Sierpinski triangle and the Mandelbrot set.
   113 Some relatively sophisticated sample programs in brainf*** are given
   112 There seems to be even a dedicated Windows IDE for bf programs, though
   114 in the file \texttt{bf.scala}, including a brainf*** program for the
   113 I am not sure whether this is just an elaborate April fools' joke---judge
   115 Sierpinski triangle and the Mandelbrot set.  There seems to be even a
   114 yourself:
   116 dedicated Windows IDE for bf programs, though I am not sure whether
       
   117 this is just an elaborate April fools' joke---judge yourself:
   115 
   118 
   116 \begin{center}
   119 \begin{center}
   117 \url{https://www.microsoft.com/en-us/p/brainf-ck/9nblgggzhvq5}
   120 \url{https://www.microsoft.com/en-us/p/brainf-ck/9nblgggzhvq5}
   118 \end{center}  \bigskip
   121 \end{center}  \bigskip
   119 
   122 
   120 
   123 
   121 \noindent
   124 \noindent
   122 As mentioned above, brainf*** has 8 single-character commands, namely
   125 As mentioned above, the original brainf*** has 8 single-character
   123 \texttt{'>'}, \texttt{'<'}, \texttt{'+'}, \texttt{'-'}, \texttt{'.'},
   126 commands. Our version of bf++ will contain the commands \texttt{'>'},
   124 \texttt{','}, \texttt{'['} and \texttt{']'}. Every other character is
   127 \texttt{'<'}, \texttt{'+'}, \texttt{'-'}, \texttt{'.'}, \texttt{'['}
   125 considered a comment.  Brainf*** operates on memory cells containing
   128 and \texttt{']'} from the original, and in addition the commands
       
   129 \texttt{'@'}, \texttt{'*'} and \texttt{'\#'}.  Every other character
       
   130 is considered a comment.
       
   131 
       
   132 Our interpreter for bf++ operates on memory cells containing
   126 integers. For this it uses a single memory pointer that points at each
   133 integers. For this it uses a single memory pointer that points at each
   127 stage to one memory cell. This pointer can be moved forward by one
   134 stage to one memory cell. This pointer can be moved forward by one
   128 memory cell by using the command \texttt{'>'}, and backward by using
   135 memory cell by using the command \texttt{'>'}, and backward by using
   129 \texttt{'<'}. The commands \texttt{'+'} and \texttt{'-'} increase,
   136 \texttt{'<'}. The commands \texttt{'+'} and \texttt{'-'} increase,
   130 respectively decrease, by 1 the content of the memory cell to which
   137 respectively decrease, by 1 the content of the memory cell to which
   131 the memory pointer currently points to. The commands for input/output
   138 the memory pointer currently points to. The command for output is
   132 are \texttt{','} and \texttt{'.'}. Output works by reading the content
   139 \texttt{'.'} whereby output works by reading the content of the memory
   133 of the memory cell to which the memory pointer points to and printing
   140 cell to which the memory pointer points to and printing it out as an
   134 it out as an ASCII character. Input works the other way, taking some
   141 ASCII character.\footnote{In the originial version of bf, there is also a
   135 user input and storing it in the cell to which the memory pointer
   142   command for input, but we omit it here. All our programs will be
   136 points to. The commands \texttt{'['} and \texttt{']'} are looping
   143   ``autonomous''.}  The
       
   144 commands \texttt{'['} and \texttt{']'} are looping
   137 constructs. Everything in between \texttt{'['} and \texttt{']'} is
   145 constructs. Everything in between \texttt{'['} and \texttt{']'} is
   138 repeated until a counter (memory cell) reaches zero.  A typical
   146 repeated until a counter (memory cell) reaches zero.  A typical
   139 program in brainf*** looks as follows:
   147 program in brainf*** looks as follows:
   140 
   148 
   141 \begin{center}
   149 \begin{center}
   144    +++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
   152    +++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
   145 \end{verbatim}
   153 \end{verbatim}
   146 \end{center}  
   154 \end{center}  
   147 
   155 
   148 \noindent
   156 \noindent
   149 This one prints out Hello World\ldots{}obviously ;o) 
   157 This one prints out Hello World\ldots{}obviously \texttt{;o)} We also
       
   158 add 3 new commands to the bf++ langauge, whose purpose we explain later.
       
   159 
   150 
   160 
   151 \subsubsection*{Tasks (file bf.scala)}
   161 \subsubsection*{Tasks (file bf.scala)}
   152 
   162 
   153 \begin{itemize}
   163 \begin{itemize}
   154 \item[(1)]  Write a function that takes a filename (a string) as an argument
   164 \item[(1)]  Write a function that takes a filename (a string) as an argument
   155   and requests the corresponding file from disk. It returns the
   165   and requests the corresponding file from disk. It returns the
   156   content of the file as a string. If the file does not exists,
   166   content of the file as a string. If the file does not exists,
   157   the function should return the empty string.\\
   167   the function should return the empty string.\\
   158   \mbox{}\hfill[1 Mark]
   168   \mbox{}\hfill[1 Mark]
   159   
   169   
   160 \item[(2)] Brainf*** memory is represented by a \texttt{Map} from
   170 \item[(2)] Brainf**k++ memory is represented by a \texttt{Map} from
   161   integers to integers. The empty memory is represented by
   171   integers to integers. The empty memory is represented by
   162   \texttt{Map()}, that is nothing is stored in the
   172   \texttt{Map()}, that is nothing is stored in the
   163   memory; \texttt{Map(0 -> 1, 2 -> 3)} stores \texttt{1} at
   173   memory; \texttt{Map(0 -> 1, 2 -> 3)} stores \texttt{1} at
   164   memory location \texttt{0}, and at \texttt{2} it stores \texttt{3}. The
   174   memory location \texttt{0}, and at \texttt{2} it stores \texttt{3}. The
   165   convention is that if we query the memory at a location that is
   175   convention is that if we query the memory at a location that is
   176   with the same data, except the new value is stored at the given memory
   186   with the same data, except the new value is stored at the given memory
   177   pointer.\hfill[1 Mark]
   187   pointer.\hfill[1 Mark]
   178 
   188 
   179 \item[(3)] Write two functions, \texttt{jumpRight} and
   189 \item[(3)] Write two functions, \texttt{jumpRight} and
   180   \texttt{jumpLeft}, that are needed to implement the loop constructs
   190   \texttt{jumpLeft}, that are needed to implement the loop constructs
   181   in brainf***. They take a program (a \texttt{String}) and a program
   191   in brainf**k++. They take a program (a \texttt{String}) and a program
   182   counter (an \texttt{Int}) as arguments and move right (respectively
   192   counter (an \texttt{Int}) as arguments and move right (respectively
   183   left) in the string in order to find the \textbf{matching}
   193   left) in the string in order to find the \textbf{matching}
   184   opening/closing bracket. For example, given the following program
   194   opening/closing bracket. For example, given the following program
   185   with the program counter indicated by an arrow:
   195   with the program counter indicated by an arrow:
   186 
   196 
   187   \begin{center}
   197   \begin{center}
   188   \texttt{--[\barbelow{.}.+>--],>,++}
   198   \texttt{--[\barbelow{.}.+>--].>.++}
   189   \end{center}
   199   \end{center}
   190 
   200 
   191   then the matching closing bracket is in 9th position (counting from 0) and
   201   then the matching closing bracket is in 9th position (counting from 0) and
   192   \texttt{jumpRight} is supposed to return the position just after this
   202   \texttt{jumpRight} is supposed to return the position just after this
   193   
   203   
   194   \begin{center}
   204   \begin{center}
   195   \texttt{--[..+>--]\barbelow{,}>,++}
   205   \texttt{--[..+>--]\barbelow{.}>.++}
   196   \end{center}
   206   \end{center}
   197 
   207 
   198   meaning it jumps to after the loop. Similarly, if you are in 8th position,
   208   meaning it jumps to after the loop. Similarly, if you are in 8th position,
   199   then \texttt{jumpLeft} is supposed to jump to just after the opening
   209   then \texttt{jumpLeft} is supposed to jump to just after the opening
   200   bracket (that is jumping to the beginning of the loop):
   210   bracket (that is jumping to the beginning of the loop):
   201 
   211 
   202   \begin{center}
   212   \begin{center}
   203     \texttt{--[..+>-\barbelow{-}],>,++}
   213     \texttt{--[..+>-\barbelow{-}].>.++}
   204     \qquad$\stackrel{\texttt{jumpLeft}}{\longrightarrow}$\qquad
   214     \qquad$\stackrel{\texttt{jumpLeft}}{\longrightarrow}$\qquad
   205     \texttt{--[\barbelow{.}.+>--],>,++}
   215     \texttt{--[\barbelow{.}.+>--].>.++}
   206   \end{center}
   216   \end{center}
   207 
   217 
   208   Unfortunately we have to take into account that there might be
   218   Unfortunately we have to take into account that there might be
   209   other opening and closing brackets on the `way' to find the
   219   other opening and closing brackets on the `way' to find the
   210   matching bracket. For example in the brainf*** program
   220   matching bracket. For example in the brain*ck++ program
   211 
   221 
   212   \begin{center}
   222   \begin{center}
   213   \texttt{--[\barbelow{.}.[+>]--],>,++}
   223   \texttt{--[\barbelow{.}.[+>]--].>.++}
   214   \end{center}
   224   \end{center}
   215 
   225 
   216   we do not want to return the index for the \texttt{'-'} in the 9th
   226   we do not want to return the index for the \texttt{'-'} in the 9th
   217   position, but the program counter for \texttt{','} in 12th
   227   position, but the program counter for \texttt{'.'} in 12th
   218   position. The easiest to find out whether a bracket is matched is by
   228   position. The easiest to find out whether a bracket is matched is by
   219   using levels (which are the third argument in \texttt{jumpLeft} and
   229   using levels (which are the third argument in \texttt{jumpLeft} and
   220   \texttt{jumpLeft}). In case of \texttt{jumpRight} you increase the
   230   \texttt{jumpLeft}). In case of \texttt{jumpRight} you increase the
   221   level by one whenever you find an opening bracket and decrease by
   231   level by one whenever you find an opening bracket and decrease by
   222   one for a closing bracket. Then in \texttt{jumpRight} you are looking
   232   one for a closing bracket. Then in \texttt{jumpRight} you are looking
   223   for the closing bracket on level \texttt{0}. For \texttt{jumpLeft} you
   233   for the closing bracket on level \texttt{0}. For \texttt{jumpLeft} you
   224   do the opposite. In this way you can find \textbf{matching} brackets
   234   do the opposite. In this way you can find \textbf{matching} brackets
   225   in strings such as
   235   in strings such as
   226 
   236 
   227   \begin{center}
   237   \begin{center}
   228   \texttt{--[\barbelow{.}.[[-]+>[.]]--],>,++}
   238   \texttt{--[\barbelow{.}.[[-]+>[.]]--].>.++}
   229   \end{center}
   239   \end{center}
   230 
   240 
   231   for which \texttt{jumpRight} should produce the position:
   241   for which \texttt{jumpRight} should produce the position:
   232 
   242 
   233   \begin{center}
   243   \begin{center}
   234   \texttt{--[..[[-]+>[.]]--]\barbelow{,}>,++}
   244   \texttt{--[..[[-]+>[.]]--]\barbelow{.}>.++}
   235   \end{center}
   245   \end{center}
   236 
   246 
   237   It is also possible that the position returned by \texttt{jumpRight} or
   247   It is also possible that the position returned by \texttt{jumpRight} or
   238   \texttt{jumpLeft} is outside the string in cases where there are
   248   \texttt{jumpLeft} is outside the string in cases where there are
   239   no matching brackets. For example
   249   no matching brackets. For example
   240 
   250 
   241   \begin{center}
   251   \begin{center}
   242   \texttt{--[\barbelow{.}.[[-]+>[.]]--,>,++}
   252   \texttt{--[\barbelow{.}.[[-]+>[.]]--.>.++}
   243   \qquad$\stackrel{\texttt{jumpRight}}{\longrightarrow}$\qquad
   253   \qquad$\stackrel{\texttt{jumpRight}}{\longrightarrow}$\qquad
   244   \texttt{--[..[[-]+>[.]]-->,++\barbelow{\;\phantom{+}}}
   254   \texttt{--[..[[-]+>[.]]-->.++\barbelow{\;\phantom{+}}}
   245   \end{center}
   255   \end{center}
   246   \hfill[2 Marks]
   256   \hfill[2 Marks]
   247 
   257 
   248 
   258 
   249 \item[(4)] Write a recursive function \texttt{compute} that runs a
   259 \item[(4)] Write a recursive function \texttt{compute} that runs a
   250   brainf*** program. It takes a program, a program counter, a memory
   260   brain*u*k++ program. It takes a program, a program counter, a memory
   251   pointer and a memory as arguments. If the program counter is outside
   261   pointer and a memory as arguments. If the program counter is outside
   252   the program string, the execution stops and \texttt{compute} returns the
   262   the program string, the execution stops and \texttt{compute} returns the
   253   memory. If the program counter is inside the string, it reads the
   263   memory. If the program counter is inside the string, it reads the
   254   corresponding character and updates the program counter \texttt{pc},
   264   corresponding character and updates the program counter \texttt{pc},
   255   memory pointer \texttt{mp} and memory \texttt{mem} according to the
   265   memory pointer \texttt{mp} and memory \texttt{mem} according to the
   256   rules shown in Figure~\ref{comms}. It then calls recursively
   266   rules shown in Figure~\ref{comms}. It then calls recursively
   257   \texttt{compute} with the updated data. The most convenient way to
   267   \texttt{compute} with the updated data. The most convenient way to
   258   implement the brainf**k rules in Scala is to use pattern-matching
   268   implement the brainf**k++ rules in Scala is to use pattern-matching
   259   and to calculate a triple consisting of the updated \texttt{pc},
   269   and to calculate a triple consisting of the updated \texttt{pc},
   260   \texttt{mp} and \texttt{mem}.
   270   \texttt{mp} and \texttt{mem}.
   261 
   271 
   262   Write another function \texttt{run} that calls \texttt{compute} with a
   272   Write another function \texttt{run} that calls \texttt{compute} with a
   263   given brainfu** program and memory, and the program counter and memory pointer
   273   given brainfu*k++ program and memory, and the program counter and memory pointer
   264   set to~$0$. Like \texttt{compute}, it returns the memory after the execution
   274   set to~$0$. Like \texttt{compute}, it returns the memory after the execution
   265   of the program finishes. You can test your brainf**k interpreter with the
   275   of the program finishes. You can test your brainf**k++ interpreter with the
   266   Sierpinski triangle or the Hello world programs (they seem to be particularly
   276   Sierpinski triangle or the Hello world programs (they seem to be particularly
   267   useful for debugging purposes), or have a look at
   277   useful for debugging purposes), or have a look at
   268 
   278 
   269   \begin{center}
   279   \begin{center}
   270   \url{https://esolangs.org/wiki/Brainfuck}
   280   \url{https://esolangs.org/wiki/Brainfuck}
   297       \hfill\texttt{'.'} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   307       \hfill\texttt{'.'} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   298                        $\bullet$ & $\texttt{pc} + 1$\\
   308                        $\bullet$ & $\texttt{pc} + 1$\\
   299                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\\
   309                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\\
   300                        $\bullet$ & print out \,\texttt{mem(mp)} as a character\\
   310                        $\bullet$ & print out \,\texttt{mem(mp)} as a character\\
   301                      \end{tabular}\\\hline   
   311                      \end{tabular}\\\hline   
   302       \hfill\texttt{','} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   312       %\hfill\texttt{','} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   303                        $\bullet$ & $\texttt{pc} + 1$\\
   313       %                 $\bullet$ & $\texttt{pc} + 1$\\
   304                        $\bullet$ & $\texttt{mp}$ unchanged\\
   314       %                 $\bullet$ & $\texttt{mp}$ unchanged\\
   305                        $\bullet$ & \texttt{mem} updated with \texttt{mp -> \textrm{input}}\\
   315       %                 $\bullet$ & \texttt{mem} updated with \texttt{mp -> \textrm{input}}\\
   306                        \multicolumn{2}{@{}l}{the input is given by \texttt{Console.in.read().toByte}}
   316       %                 \multicolumn{2}{@{}l}{the input is given by \texttt{Console.in.read().toByte}}
   307                      \end{tabular}\\\hline   
   317       %               \end{tabular}\\\hline   
   308       \hfill\texttt{'['} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   318       \hfill\texttt{'['} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   309                        \multicolumn{2}{@{}l}{if \texttt{mem(mp) == 0} then}\\
   319                        \multicolumn{2}{@{}l}{if \texttt{mem(mp) == 0} then}\\
   310                        $\bullet$ & $\texttt{pc = jumpRight(prog, pc + 1, 0)}$\\
   320                        $\bullet$ & $\texttt{pc = jumpRight(prog, pc + 1, 0)}$\\
   311                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\medskip\\
   321                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\medskip\\
   312                        \multicolumn{2}{@{}l}{otherwise if \texttt{mem(mp) != 0} then}\\
   322                        \multicolumn{2}{@{}l}{otherwise if \texttt{mem(mp) != 0} then}\\
   319                        $\bullet$ & $\texttt{pc = jumpLeft(prog, pc - 1, 0)}$\\
   329                        $\bullet$ & $\texttt{pc = jumpLeft(prog, pc - 1, 0)}$\\
   320                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\medskip\\
   330                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\medskip\\
   321                        \multicolumn{2}{@{}l}{otherwise if \texttt{mem(mp) == 0} then}\\
   331                        \multicolumn{2}{@{}l}{otherwise if \texttt{mem(mp) == 0} then}\\
   322                        $\bullet$ & $\texttt{pc} + 1$\\
   332                        $\bullet$ & $\texttt{pc} + 1$\\
   323                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\\
   333                        $\bullet$ & $\texttt{mp}$ and \texttt{mem} unchanged\\
   324                      \end{tabular}\\\hline   
   334                            \end{tabular}\\\hline
       
   335       \hfill\texttt{'@'} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
       
   336                        $\bullet$ & $\texttt{pc} + 1$\\
       
   337                        $\bullet$ & $\texttt{mp}$ unchanged\\
       
   338                        $\bullet$ & \texttt{mem} updated with \texttt{mp -> \textrm{input}}\\
       
   339                        \multicolumn{2}{@{}l}{the input is given by \texttt{Console.in.read().toByte}}
       
   340                            \end{tabular}\\\hline
       
   341       \hfill\texttt{'*'} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
       
   342                        $\bullet$ & $\texttt{pc} + 1$\\
       
   343                        $\bullet$ & $\texttt{mp}$ unchanged\\
       
   344                        $\bullet$ & \texttt{mem} updated with \texttt{mp -> \textrm{input}}\\
       
   345                        \multicolumn{2}{@{}l}{the input is given by \texttt{Console.in.read().toByte}}
       
   346                            \end{tabular}\\\hline
       
   347       \hfill\texttt{'\#'} & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
       
   348                        $\bullet$ & $\texttt{pc} + 1$\\
       
   349                        $\bullet$ & $\texttt{mp}$ unchanged\\
       
   350                        $\bullet$ & \texttt{mem} updated with \texttt{mp -> \textrm{input}}\\
       
   351                        \multicolumn{2}{@{}l}{the input is given by \texttt{Console.in.read().toByte}}
       
   352                      \end{tabular}\\\hline  
   325       any other char & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   353       any other char & \begin{tabular}[t]{@{}l@{\hspace{2mm}}l@{}}
   326                          $\bullet$ & $\texttt{pc} + 1$\\
   354                          $\bullet$ & $\texttt{pc} + 1$\\
   327                          $\bullet$ & \texttt{mp} and \texttt{mem} unchanged
   355                          $\bullet$ & \texttt{mp} and \texttt{mem} unchanged
   328                        \end{tabular}\\
   356                        \end{tabular}\\
   329       \hline                 
   357       \hline