% !TeX root = forth.tex
\chapter{The optional Exception word set} % 9
\wordlist{exception}

\section{Introduction} % 9.1

\section{Additional terms and notation} % 9.2
None.

\section{Additional usage requirements} % 9.3

\subsection{THROW values} % 9.3.1
\label{exception:throw}

The \word{THROW} values \{-255{\ldots}-1\} shall be used only as
assigned by this standard. The values \{-4095{\ldots}-256\}
shall be used only as assigned by a system.

Programs shall not define values for use with \word{THROW} in the
range \{-4095{\ldots}-1\}.

\subsection{Exception frame} % 9.3.2

An exception frame is the implementation-dependent set of
information recording the current execution state necessary for
the proper functioning of \word{CATCH} and \word{THROW}. It often
includes the depths of the data stack and return stack.

\subsection{Exception stack} % 9.3.3

A stack used for the nesting of exception frames by \word{CATCH}
and \word{THROW}. It may be, but need not be, implemented using
the return stack.


\subsection{Possible actions on an ambiguous condition} % 9.3.5
\label{exception:ambiguous}

A system choosing to execute \word{THROW} when detecting one of the
ambiguous conditions listed in table \ref{table:throw} shall use the
throw code listed there.

See: \xref[3.4.4 Possible actions on an ambiguous condition]{usage:ambiguous}.

% \throwdef[<extension>]{<code>}{<description>}
%	Define a new throw code

\newcommand{\throwdef}[3][\empty]{%
	\ifx\empty#1%
		\defthrowcode{#2}{#3}
		\newline
	\else
		\cbstart
			\uline{\defthrowcode{#2}{#3}}
			\hfill{\tiny\textsf{#1}}
		\cbend\newline
	\fi
}

% Helper function for \throwdef.

\newcommand{\defthrowcode}[2]{%
	\makebox[1.6em][r]{#1}\hspace{1em}#2
}

\begin{table}[!ht]
	\begin{center}
		\caption{\word[exception]{THROW} code assignments}
		\label{table:throw}
		\small
		\newlength{\colwidth}
		\setlength{\colwidth}{20.5em}
		\begin{tabular}{p{\colwidth}p{\colwidth}}
			\hline\hline
			Code Reserved for & Code Reserved for \\\hline
			\multicolumn{2}{}{} \\[-2ex]
			\begin{minipage}[t]{\colwidth}
\throwdef{-1}{\word{ABORT}}
\throwdef{-2}{\word{ABORTq}}
\throwdef{-3}{stack overflow}
\throwdef{-4}{stack underflow}
\throwdef{-5}{return stack overflow}
\throwdef{-6}{return stack underflow}
\throwdef{-7}{do-loops nested too deeply during execution}
\throwdef{-8}{dictionary overflow}
\throwdef{-9}{invalid memory address}
\throwdef{-10}{division by zero}
\throwdef{-11}{result out of range}
\throwdef{-12}{argument type mismatch}
\throwdef{-13}{undefined word}
\throwdef{-14}{interpreting a compile-only word}
\throwdef{-15}{invalid \word[tools]{FORGET}}
\throwdef{-16}{attempt to use zero-length string as a name}
\throwdef{-17}{pictured numeric output string overflow}
\throwdef{-18}{parsed string overflow}
\throwdef{-19}{definition name too long}
\throwdef{-20}{write to a read-only location}
\throwdef{-21}{unsupported operation}
\throwdef{}{(e.g., \word[facility]{AT-XY} on a too-dumb terminal)}
\throwdef{-22}{control structure mismatch}
\throwdef{-23}{address alignment exception}
\throwdef{-24}{invalid numeric argument}
\throwdef{-25}{return stack imbalance}
\throwdef{-26}{loop parameters unavailable}
\throwdef{-27}{invalid recursion}
\throwdef{-28}{user interrupt}
\throwdef{-29}{compiler nesting}
\throwdef{-30}{obsolescent feature}
\throwdef{-31}{\word[core]{toBODY} used on non-\word[core]{CREATE}d definition}
\throwdef{-32}{invalid \param{name} argument (e.g., \word[core]{TO} \param{name})}
\throwdef{-33}{block read exception}
\throwdef{-34}{block write exception}
\throwdef{-35}{invalid block number}
\throwdef{-36}{invalid file position}
\throwdef{-37}{file I/O exception}
\throwdef{-38}{non-existent file}
\throwdef{-39}{unexpected end of file}
			\end{minipage} &
			\begin{minipage}[t]{\colwidth}
\throwdef{-40}{invalid \word[core]{BASE} for floating point conversion}
\throwdef{-41}{loss of precision}
\throwdef{-42}{floating-point divide by zero}
\throwdef{-43}{floating-point result out of range}
\throwdef{-44}{floating-point stack overflow}
\throwdef{-45}{floating-point stack underflow}
\throwdef{-46}{floating-point invalid argument}
\throwdef{-47}{compilation word list deleted}
\throwdef{-48}{invalid \word[core]{POSTPONE}}
\throwdef{-49}{search-order overflow}
\throwdef{-50}{search-order underflow}
\throwdef{-51}{compilation word list changed}
\throwdef{-52}{control-flow stack overflow}
\throwdef{-53}{exception stack overflow}
\throwdef{-54}{floating-point underflow}
\throwdef{-55}{floating-point unidentified fault}
\throwdef{-56}{\word[core]{QUIT}}
\throwdef{-57}{exception in sending or receiving a character}
\throwdef{-58}{\word[tools]{[IF]}, \word[tools]{[ELSE]}, or \word[tools]{[THEN]} exception}
\throwdef{-59}{\word[memory]{ALLOCATE}}
\throwdef{-60}{\word[memory]{FREE}}
\throwdef{-61}{\word[memory]{RESIZE}}
\throwdef{-62}{\word[file]{CLOSE-FILE}}
\throwdef{-63}{\word[file]{CREATE-FILE}}
\throwdef{-64}{\word[file]{DELETE-FILE}}
\throwdef{-65}{\word[file]{FILE-POSITION}}
\throwdef{-66}{\word[file]{FILE-SIZE}}
\throwdef{-67}{\word[file]{FILE-STATUS}}
\throwdef{-68}{\word[file]{FLUSH-FILE}}
\throwdef{-69}{\word[file]{OPEN-FILE}}
\throwdef{-70}{\word[file]{READ-FILE}}
\throwdef{-71}{\word[file]{READ-LINE}}
\throwdef{-72}{\word[file]{RENAME-FILE}}
\throwdef{-73}{\word[file]{REPOSITION-FILE}}
\throwdef{-74}{\word[file]{RESIZE-FILE}}
\throwdef{-75}{\word[file]{WRITE-FILE}}
\throwdef{-76}{\word[file]{WRITE-LINE}}
\throwdef{-77}{Malformed xchar}
\throwdef{-78}{\word[string]{SUBSTITUTE}}
\throwdef{-79}{\word[string]{REPLACES}}
			\end{minipage}
			\\[-2ex] \hline\hline
		\end{tabular}
	\end{center}
\end{table}


\subsection{Exception handling} % 9.3.6

There are several methods of coupling \word{CATCH} and \word{THROW}
to other procedural nestings. The usual nestings are the execution
of definitions, use of the return stack, use of loops,
instantiation of locals and nesting of input sources (i.e., with
\word[block]{LOAD}, \word[core]{EVALUATE}, or
\word[file]{INCLUDE-FILE}).

When a \word{THROW} returns control to a \word{CATCH}, the system
shall un-nest not only definitions, but also, if present, locals
and input source specifications, to return the system to its proper
state for continued execution past the \word{CATCH}.

\section{Additional documentation requirements} % 9.4

\subsection{System documentation} % 9.4.1

\subsubsection{Implementation-defined options} % 9.4.1.1
\begin{itemize}
\item Values used in the system by \wref{exception:CATCH}{CATCH} and
	\wref{exception:THROW}{THROW}
	(\xref[9.3.1 THROW values]{exception:throw},
	 \xref[9.3.5 Possible actions on an ambiguous condition]{exception:ambiguous}).
\end{itemize}

\subsubsection{Ambiguous conditions} % 9.4.1.2
\begin{itemize}
\item no additional requirements.
\end{itemize}

\subsubsection{Other system documentation} % 9.4.1.3
\begin{itemize}
\item no additional requirements.
\end{itemize}

\subsection{Program documentation} % 9.4.2
\begin{itemize}
\item no additional requirements.
\end{itemize}

\section{Compliance and labeling} % 9.5

\subsection{Forth-\snapshot{} systems} % 9.5.1

The phrase ``Providing the Exception word set'' shall be appended to
the label of any Standard System that provides all of the Exception
word set.

The phrase ``Providing \emph{name(s)} from the Exception Extensions
word set'' shall be appended to the label of any Standard System
that provides portions of the Exception Extensions word set.

The phrase ``Providing the Exception Extensions word set'' shall be
appended to the label of any Standard System that provides all of
the Exception and Exception Extensions word sets.

\subsection{Forth-\snapshot{} programs} % 9.5.2

The phrase ``Requiring the Exception word set'' shall be appended
to the label of Standard Programs that require the system to provide
the Exception word set.

The phrase ``Requiring \emph{name(s)} from the Exception Extensions
word set'' shall be appended to the label of Standard Programs that
require the system to provide portions of the Exception Extensions
word set.

The phrase ``Requiring the Exception Extensions word set'' shall be
appended to the label of Standard Programs that require the system
to provide all of the Exception and Exception Extensions word sets.

\newpage
\section{Glossary} % 9.6

\subsection{Exception words} % 9.6.1

\begin{worddef}{0875}{CATCH}
\item \stack{i*x xt}{j*x 0 | i*x n}

	Push an exception frame on the exception stack and then execute
	the execution token \param{xt} (as with \word[core]{EXECUTE}) in
	such a way that control can be transferred to a point just after
	\word{CATCH} if \word{THROW} is executed during the execution of
	\param{xt}.

	If the execution of \param{xt} completes normally (i.e., the
	exception frame pushed by this \word{CATCH} is not popped by an
	execution of \word{THROW}) pop the exception frame and return
	zero on top of the data stack, above whatever stack items would
	have been returned by \param{xt} \word[core]{EXECUTE}. Otherwise,
	the remainder of the execution semantics are given by
	\word{THROW}.

\see \rref{exception:THROW}{}.

	\begin{implement} % I.9.1.0875 CATCH
	\dffamily
		This sample implementation of \word{CATCH} uses the non-standard
		words described below.  They or their equivalents are available in many
		systems.  Other implementation strategies, including directly saving the
		value of \word[core]{DEPTH}, are possible if such words are not available.

		\begin{description}
		\item[\texttt{SP@}] \stack{}{addr} \\
			returns the address corresponding to the top of data stack.

		\item[\texttt{SP!}] \stack{addr}{} \\
			sets the stack pointer to \emph{addr}, thus restoring the stack
			depth to the same depth that existed just before \emph{addr} was
			acquired by executing \texttt{SP@}.

		\item[\texttt{RP@}] \stack{}{addr} \\
			returns the address corresponding to the top of return stack.

		\item[\texttt{RP!}] \stack{addr}{} \\
			sets the return stack pointer to \emph{addr}, thus restoring the
			return stack depth to the same depth that existed just before
			\emph{addr} was acquired by executing \texttt{RP@}.
		\end{description}

		\ttfamily
		\begin{tabbing}
		\tab \= \tab \= \hspace{7em} \= ( saved-sp ) \= \kill
		\word{VARIABLE} HANDLER ~ 0 HANDLER \word{!} ~ \word{bs} \textdf{last exception handler} \\[\parskip]

		\+ \word{:} \word{CATCH} ~ \word{p} xt -{}- exception\# | 0  \word{bs} \textdf{return addr on stack} \\
			SP@ \word{toR}					\>\> \word{p} xt )\> \word{bs} \textdf{save data stack pointer} \\
			HANDLER \word{@} \word{toR}		\>\> \word{p} xt )\> \word{bs} \textdf{and previous handler} \\
			RP@ HANDLER \word{!}			\>\> \word{p} xt )\> \word{bs} \textdf{set current handler} \\
			\word{EXECUTE}					\>\> \word{p} )	  \> \word{bs} \textdf{execute returns if no} THROW \\
			\word{Rfrom} HANDLER \word{!}	\>\> \word{p} )   \> \word{bs} \textdf{restore previous handler} \\
			\word{Rfrom} \word{DROP}		\>\> \word{p} )   \> \word{bs} \textdf{discard saved stack ptr} \\
		\-	0								\>\> \word{p} 0 ) \> \word{bs} \textdf{normal completion} \\
		\word{;}
		\end{tabbing}

		\dffamily
		In a multi-tasking system, the \texttt{HANDLER} variable should be in
		the per-task variable area (i.e., a user variable).

		This sample implementation does not explicitly handle the case in
		which \word{CATCH} has never been called (i.e., the \word{ABORT}
		behavior). One solution would be to execute a \word{CATCH} within
		\word{QUIT}, so that there is always an ``exception handler of last
		resort'' present, as shown in \iref{core:QUIT}{}.
	\end{implement}

	\begin{testing}
		See \tref{exception:THROW}{}.
	\end{testing}
\end{worddef}


\begin{worddef}{2275}{THROW}
\item \stack{k*x n}{k*x | i*x n}

	If any bits of \param{n} are non-zero, pop the topmost exception
	frame from the exception stack, along with everything on the
	return stack above that frame. Then restore the input source
	specification in use before the corresponding \word{CATCH}
	and adjust the depths of all stacks defined by this standard
	so that they are the same as the depths saved in the exception
	frame (\param{i} is the same number as the \param{i} in the input
	arguments to the corresponding \word{CATCH}), put \param{n} on
	top of the data stack, and transfer control to a point just after
	the \word{CATCH} that pushed that exception frame.

	If the top of the stack is non zero and there is no exception
	frame on the exception stack, the behavior is as follows:

	If \param{n} is minus-one (-1), perform the function of
	\wref{core:ABORT}{ABORT} (the version of \word[core]{ABORT} in
	the Core word set), displaying no message.

	If \param{n} is minus-two, perform the function of
	\wref{core:ABORTq}{ABORT"} (the version of \word[core]{ABORTq}
	in the Core word set), displaying the characters \param{ccc}
	associated with the \word{ABORTq} that generated the
	\word{THROW}.

	Otherwise, the system may display an implementation-dependent
	message giving information about the condition associated with
	the \word{THROW} code \param{n}. Subsequently, the system shall
	perform the function of \wref{core:ABORT}{ABORT} (the version
	of \word[core]{ABORT} in the Core word set).

\see \rref{exception:THROW}{}.

	\begin{rationale} % A.9.6.1.2275 THROW
		If \word{THROW} is executed with a non zero argument, the effect
		is as if the corresponding \word{CATCH} had returned it. In that
		case, the stack depth is the same as it was just before \word{CATCH}
		began execution. The values of the \param{i*x} stack arguments could
		have been modified arbitrarily during the execution of \param{xt}.
		In general, nothing useful may be done with those stack items, but
		since their number is known (because the stack depth is deterministic),
		the application may \word[core]{DROP} them to return to a predictable
		stack state.

		Typical use:
		\setwordlist{core}
		\begin{quote}\ttfamily
			\word{:} could-fail \word{p} -{}- char ) \\
			\tab \word{KEY} \word{DUP} \word{[CHAR]} Q \word{=}~
				\word{IF}~ 1 \word[exception]{THROW}
				\word{THEN}
			\word{;}

			\word{:} do-it \word{p} a b -{}- c) ~
				\word{2DROP} could-fail \word{;}

			\word{:} try-it \word{p} -{}-) \\
			\tab 1 2 \word{[']} do-it~ \word[exception]{CATCH}~ \word{IF} \\
			\tab~~ \word{p} x1 x2 ) \word{2DROP}
				\word{.q}  There was an exception" \word{CR} \\
			\tab \word{ELSE}
				\word{.q} The character was " \word{EMIT} \word{CR} \\
			\tab \word{THEN} \\
			\word{;}

			\word{;} retry-it \word{p} -{}- ) \\
			\tab \word{BEGIN}  1 2 \word{[']} do-it \word[exception]{CATCH}~
				\word{WHILE} \\
			\tab~~ \word{p} x1 x2) \word{2DROP}
				\word{.q} Exception, keep trying" \word{CR} \\
			\tab \word{REPEAT} \word{p} char ) \\
			\tab \word{.q} The character was " \word{EMIT} \word{CR} \\
			\word{;}
		\end{quote}
		\setwordlist{exception}
	\end{rationale}

	\begin{implement}
		\textdf{This is the counter part to \iref{exception:CATCH}{}.}

		\begin{tabbing}
		\tab \= \tab \= \hspace{7em} \= ( saved-sp ) \= \kill
		\+ \word{:} \word{THROW} \word{p} ??? exception\# -{}- ??? exception\# ) \\
			\+ \word{qDUP} \word{IF}			\>	\> \word{p} exc\# )		\> \word{bs} 0 THROW \textdf{is no-op} \\
				HANDLER \word{@} RP!				\> \word{p} exc\# )		\> \word{bs} \textdf{restore prev return stack} \\
				\word{Rfrom} HANDLER \word{!}		\> \word{p} exc\# )		\> \word{bs} \textdf{restore prev handler} \\
				\word{Rfrom} \word{SWAP} \word{toR}	\> \word{p} saved-sp )	\> \word{bs} exc\# \textdf{on return stack} \\
				SP! \word{DROP} \word{Rfrom}		\> \word{p} exc\# )		\> \word{bs} \textdf{restore stack} \\
				\word{bs} \textdf{Return to the caller of CATCH because return} \\
				\word{bs} \textdf{stack is restored to the state that existed} \\
			\-	\word{bs} \textdf{when CATCH began execution} \\
		\- \word{THEN} \\
		\word{;}
		\end{tabbing}
	\end{implement}

	\begin{testing} \ttfamily
		\word{DECIMAL}

		\word{:} t1 9 \word{;} \\
		\word{:} c1 1 2 3 \word{[']} t1 \word{CATCH} \word{;} \\
		\test{c1}{1 2 3 9 0} \tab \word{bs} \textdf{No THROW executed}

		\word{:} t2 8 0 \word{THROW} \word{;} \\
		\word{:} c2 1 2 \word{[']} t2 \word{CATCH} \word{;} \\
		\test{c2}{1 2 8 0} \tab \word{bs} \textdf{0 THROW does nothing}

		\word{:} t3 7 8 9 99 \word{THROW} \word{;} \\
		\word{:} c3 1 2 \word{[']} t3 \word{CATCH} \word{;}\\
		\test{c3}{1 2 99} \tab \word{bs} \textdf{Restores stack to \word{CATCH} depth}

		\word{:} t4 \word{1-} \word{DUP} \word{0more} \word{IF} \word{RECURSE} \word{ELSE} 999 \word{THROW} -222 \word{THEN} \word{;} \\
		\word{:} c4 3 4 5 10 \word{[']} t4 \word{CATCH} -111 \word{;} \\
		\test{c4}{3 4 5 0 999 -111} \tab[3] \word{bs} \textdf{Test return stack unwinding}

		\word{:} t5 \word{2DROP} \word{2DROP} 9999 \word{THROW} \word{;} \\
		\word{:} c5 1 2 3 4 \word{[']} t5 \word{CATCH} \tab[4.5] \word{bs} \textdf{Test depth restored correctly} \\
		\tab \word{DEPTH} \word{toR} \word{DROP} \word{2DROP} \word{2DROP} \word{Rfrom} \word{;} \tab \word{bs} \textdf{after stack has been emptied} \\
		\test{c5}{5}
	\end{testing}
\end{worddef}

\newpage
\subsection{Exception extension words} % 9.6.2
\extended

\begin{worddef}{0670}{ABORT}
\item Extend the semantics of \wref{core:ABORT}{ABORT} to be:

	\stack{i*x}{}
	\stack[R]{j*x}{}

	Perform the function of \texttt{-1} \word{THROW}.

\see \wref{core:ABORT}{ABORT}.

	\begin{implement} % I.9.1.0875 CATCH
		\word{:} \word{ABORT} ~ -1 \word{THROW} ~ \word{;}
	\end{implement}

	\begin{testing}
		See \tref{exception:ABORTq}{}.
	\end{testing}
\end{worddef}


\begin{worddef}[ABORTq]{0680}{ABORT"}[abort-quote]
\item Extend the semantics of \wref{core:ABORTq}{ABORT"} to be:

\interpret
	Interpretation semantics for this word are undefined.

\compile
	\stack{"ccc<quote>"}{}

	Parse \param{ccc} delimited by a \texttt{"} (double-quote).
	Append the run-time semantics given below to the current
	definition.

\runtime
	\stack{i*x x_1}{| i*x}
	\stack[R]{j*x}{| j*x}

	Remove \param{x_1} from the stack. If any bit of \param{x_1}
	is not zero, perform the function of \texttt{-2} \word{THROW},
	displaying \param{ccc} if there is no exception frame on the
	exception stack.

\see \xref[3.4.1 Parsing]{usage:parsing},
	\wref{core:ABORTq}{ABORT"}.

	\begin{testing}\ttfamily
		\word{DECIMAL} \\
		\mbox{}~-1	\word{CONSTANT} exc\_abort \\
		\mbox{}~-2 \word{CONSTANT} exc\_abort" \\
		-13 \word{CONSTANT} exc\_undef \\
		\word{:} t6 \word{ABORT} \word{;}

		\textdf{The 77 in \texttt{t10} is necessary for the second
			\word{ABORTq} test as the data stack is restored to a
			depth of 2 when \word{THROW} is executed.  The 77 ensures
			the top of stack value is known for the results check.}

		\word{:} t10 77 \word{SWAP} \word{ABORTq} This should not be displayed" \word{;} \\
		\word{:} c6 \word{CATCH} \\
		\tab \word{CASE} exc\_abort~ \word{OF} 11 \word{ENDOF} \\
		\tab[3.5]		 exc\_abort" \word{OF} 12 \word{ENDOF} \\
		\tab[3.5]		 exc\_undef~ \word{OF} 13 \word{ENDOF} \\
		\tab \word{ENDCASE} \\
		\word{;}

		\test{1 2 \word{'}  t6 c6}{1 2 11 } \tab \word{bs} \textdf{Test that ABORT is caught} \\
		\test{3 0 \word{'} t10 c6}{3 77   } \tab \word{bs} \textdf{ABORT" does nothing} \\
		\test{4 5 \word{'} t10 c6}{4 77 12} \tab \word{bs} \textdf{ABORT" caught, no message}
	\end{testing}
\end{worddef}
