src/Doc/Implementation/ML.thy
changeset 78742 b2216709a839
parent 78741 39498d504f43
equal deleted inserted replaced
78741:39498d504f43 78742:b2216709a839
  1068 
  1068 
  1069 section \<open>Exceptions \label{sec:exceptions}\<close>
  1069 section \<open>Exceptions \label{sec:exceptions}\<close>
  1070 
  1070 
  1071 text \<open>
  1071 text \<open>
  1072   The Standard ML semantics of strict functional evaluation together with
  1072   The Standard ML semantics of strict functional evaluation together with
  1073   exceptions is rather well defined, but some delicate points need to be
  1073   exceptions is rather well defined, but some fine points need to be observed
  1074   observed to avoid that ML programs go wrong despite static type-checking.
  1074   to avoid that ML programs go wrong despite static type-checking.
       
  1075 
       
  1076   Unlike official Standard ML, Isabelle/ML rejects catch-all patterns in
       
  1077   \<^ML_text>\<open>handle\<close> clauses: this improves the robustness of ML programs,
       
  1078   especially against arbitrary physical events (interrupts).
       
  1079 
  1075   Exceptions in Isabelle/ML are subsequently categorized as follows.
  1080   Exceptions in Isabelle/ML are subsequently categorized as follows.
  1076 \<close>
  1081 \<close>
  1077 
  1082 
  1078 paragraph \<open>Regular user errors.\<close>
  1083 paragraph \<open>Regular user errors.\<close>
  1079 text \<open>
  1084 text \<open>
  1098 \<close>
  1103 \<close>
  1099 
  1104 
  1100 paragraph \<open>Program failures.\<close>
  1105 paragraph \<open>Program failures.\<close>
  1101 text \<open>
  1106 text \<open>
  1102   There is a handful of standard exceptions that indicate general failure
  1107   There is a handful of standard exceptions that indicate general failure
  1103   situations, or failures of core operations on logical entities (types,
  1108   situations (e.g.\ \<^ML>\<open>Fail\<close>), or failures of core operations on logical
  1104   terms, theorems, theories, see \chref{ch:logic}).
  1109   entities (types, terms, theorems, theories, see \chref{ch:logic}).
  1105 
  1110 
  1106   These exceptions indicate a genuine breakdown of the program, so the main
  1111   These exceptions indicate a genuine breakdown of the program, so the main
  1107   purpose is to determine quickly what has happened where. Traditionally, the
  1112   purpose is to determine quickly what has happened in the ML program.
  1108   (short) exception message would include the name of an ML function, although
  1113   Traditionally, the (short) exception message would include the name of an ML
  1109   this is not strictly necessary, because the ML runtime system attaches
  1114   function, although this is not strictly necessary, because the ML runtime
  1110   detailed source position stemming from the corresponding \<^ML_text>\<open>raise\<close>
  1115   system attaches detailed source position stemming from the corresponding
  1111   keyword.
  1116   \<^ML_text>\<open>raise\<close> keyword.
  1112 
  1117 
  1113   \<^medskip>
  1118   \<^medskip>
  1114   User modules can always introduce their own custom exceptions locally, e.g.\
  1119   User modules can always introduce their own custom exceptions locally, e.g.\
  1115   to organize internal failures robustly without overlapping with existing
  1120   to organize internal failures robustly without overlapping with existing
  1116   exceptions. Exceptions that are exposed in module signatures require extra
  1121   exceptions. Exceptions that are exposed in module signatures require extra
  1127 
  1132 
  1128   This is the one and only way that physical events can intrude an Isabelle/ML
  1133   This is the one and only way that physical events can intrude an Isabelle/ML
  1129   program. Such an interrupt can mean out-of-memory, stack overflow, timeout,
  1134   program. Such an interrupt can mean out-of-memory, stack overflow, timeout,
  1130   internal signaling of threads, or a POSIX process signal. An Isabelle/ML
  1135   internal signaling of threads, or a POSIX process signal. An Isabelle/ML
  1131   program that intercepts interrupts becomes dependent on physical effects of
  1136   program that intercepts interrupts becomes dependent on physical effects of
  1132   the environment. Even worse, exception handling patterns that are too
  1137   the environment (e.g.\ via \<^ML>\<open>Exn.capture\<close> without subsequent
  1133   general by accident, e.g.\ by misspelled exception constructors, will cover
  1138   \<^ML>\<open>Exn.release\<close>).
  1134   interrupts unintentionally and thus render the program semantics
  1139 
  1135   ill-defined.
  1140   Note that the original SML90 language had an \<^verbatim>\<open>Interrupt\<close> exception, but
  1136 
  1141   that was excluded from SML97 to simplify ML the mathematical semantics.
  1137   Note that the Interrupt exception dates back to the original SML90 language
  1142   Isabelle/ML does support physical interrupts thanks to special features of
  1138   definition. It was excluded from the SML97 version to avoid its malign
  1143   the underlying Poly/ML compiler and runtime system. This works robustly,
  1139   impact on ML program semantics, but without providing a viable alternative.
  1144   because the old \<^ML_text>\<open>Interrupt\<close> constructor has been removed from the
  1140   Isabelle/ML recovers physical interruptibility (which is an indispensable
  1145   ML environment, and catch-all patterns \<^ML_text>\<open>handle\<close> are rejected.
  1141   tool to implement managed evaluation of command transactions), but requires
  1146   Thus user code becomes strictly transparent wrt.\ interrupts: physical
  1142   user code to be strictly transparent wrt.\ interrupts.
  1147   events are exposed to the toplevel, and the mathematical meaning of the
  1143 
  1148   program becomes a partial function that is otherwise unchanged.
  1144   \begin{warn}
  1149 
  1145   Isabelle/ML user code needs to terminate promptly on interruption, without
  1150   The Isabelle/ML antiquotation @{ML_antiquotation try}, with its syntactic
  1146   guessing at its meaning to the system infrastructure. Temporary handling of
  1151   variants for \<^ML_text>\<open>catch\<close> or \<^ML_text>\<open>finally\<close>, supports
  1147   interrupts for cleanup of global resources etc.\ needs to be followed
  1152   intermediate handling of interrupts and subsequent cleanup-operations,
  1148   immediately by re-raising of the original exception.
  1153   without swallowing such physical event.
  1149   \end{warn}
       
  1150 \<close>
  1154 \<close>
  1151 
  1155 
  1152 text %mlref \<open>
  1156 text %mlref \<open>
  1153   \begin{mldecls}
  1157   \begin{mldecls}
  1154   @{define_ML try: "('a -> 'b) -> 'a -> 'b option"} \\
  1158   @{define_ML try: "('a -> 'b) -> 'a -> 'b option"} \\
  1158   @{define_ML Exn.is_interrupt: "exn -> bool"} \\
  1162   @{define_ML Exn.is_interrupt: "exn -> bool"} \\
  1159   @{define_ML Exn.reraise: "exn -> 'a"} \\
  1163   @{define_ML Exn.reraise: "exn -> 'a"} \\
  1160   @{define_ML Runtime.exn_trace: "(unit -> 'a) -> 'a"} \\
  1164   @{define_ML Runtime.exn_trace: "(unit -> 'a) -> 'a"} \\
  1161   \end{mldecls}
  1165   \end{mldecls}
  1162 
  1166 
  1163   \<^descr> \<^ML>\<open>try\<close>~\<open>f x\<close> makes the partiality of evaluating \<open>f x\<close> explicit via the
  1167   \<^descr> \<^ML>\<open>try\<close>~\<open>f x\<close> makes the partiality of evaluating \<open>f x\<close> explicit via
  1164   option datatype. Interrupts are \<^emph>\<open>not\<close> handled here, i.e.\ this form serves
  1168   the option datatype. Interrupts are \<^emph>\<open>not\<close> handled here, i.e.\ this form
  1165   as safe replacement for the \<^emph>\<open>unsafe\<close> version \<^ML_text>\<open>(SOME\<close>~\<open>f
  1169   serves as safe replacement for the \<^emph>\<open>fragile\<close> version \<^ML_text>\<open>(SOME\<close>~\<open>f
  1166   x\<close>~\<^ML_text>\<open>handle _ => NONE)\<close> that is occasionally seen in books about
  1170   x\<close>~\<^ML_text>\<open>handle _ => NONE)\<close> that is occasionally seen in books about
  1167   SML97, but not in Isabelle/ML.
  1171   SML97.
  1168 
  1172 
  1169   \<^descr> \<^ML>\<open>can\<close> is similar to \<^ML>\<open>try\<close> with more abstract result.
  1173   \<^descr> \<^ML>\<open>can\<close> is similar to \<^ML>\<open>try\<close> with more abstract result.
  1170 
  1174 
  1171   \<^descr> \<^ML>\<open>ERROR\<close>~\<open>msg\<close> represents user errors; this exception is normally
  1175   \<^descr> \<^ML>\<open>ERROR\<close>~\<open>msg\<close> represents user errors; this exception is normally
  1172   raised indirectly via the \<^ML>\<open>error\<close> function (see
  1176   raised indirectly via the \<^ML>\<open>error\<close> function (see
  1173   \secref{sec:message-channels}).
  1177   \secref{sec:message-channels}).
  1174 
  1178 
  1175   \<^descr> \<^ML>\<open>Fail\<close>~\<open>msg\<close> represents general program failures.
  1179   \<^descr> \<^ML>\<open>Fail\<close>~\<open>msg\<close> represents general program failures, but not user errors.
  1176 
  1180 
  1177   \<^descr> \<^ML>\<open>Exn.is_interrupt\<close> identifies interrupts robustly, without mentioning
  1181   \<^descr> \<^ML>\<open>Exn.is_interrupt\<close> identifies interrupts, without mentioning
  1178   concrete exception constructors in user code. Handled interrupts need to be
  1182   concrete exception constructors in user code. Since \<^ML_text>\<open>handle\<close> with
  1179   re-raised promptly!
  1183   catch-all patterns is rejected, it cannot handle interrupts at all. In the
       
  1184   rare situations where this is really required, use \<^ML>\<open>Exn.capture\<close> and
       
  1185   \<^ML>\<open>Exn.release\<close> (\secref{sec:managed-eval}).
  1180 
  1186 
  1181   \<^descr> \<^ML>\<open>Exn.reraise\<close>~\<open>exn\<close> raises exception \<open>exn\<close> while preserving its implicit
  1187   \<^descr> \<^ML>\<open>Exn.reraise\<close>~\<open>exn\<close> raises exception \<open>exn\<close> while preserving its implicit
  1182   position information (if possible, depending on the ML platform).
  1188   position information (if possible, depending on the ML platform).
  1183 
  1189 
  1184   \<^descr> \<^ML>\<open>Runtime.exn_trace\<close>~\<^ML_text>\<open>(fn () =>\<close>~\<open>e\<close>\<^ML_text>\<open>)\<close> evaluates
  1190   \<^descr> \<^ML>\<open>Runtime.exn_trace\<close>~\<^ML_text>\<open>(fn () =>\<close>~\<open>e\<close>\<^ML_text>\<open>)\<close> evaluates
  1199 
  1205 
  1200   \<^rail>\<open>
  1206   \<^rail>\<open>
  1201     (@@{ML_antiquotation try} | @@{ML_antiquotation can}) embedded
  1207     (@@{ML_antiquotation try} | @@{ML_antiquotation can}) embedded
  1202   \<close>
  1208   \<close>
  1203 
  1209 
  1204   \<^descr> \<open>@{try}\<close> and \<open>{can}\<close> are similar to the corresponding functions, but the
  1210 
  1205   argument is taken directly as ML expression: functional abstraction and
  1211   \<^descr> \<open>@{try}\<close> and \<open>{can}\<close> take embedded ML source as arguments, and modify the
  1206   application is done implicitly.
  1212   evaluation analogously to the combinators \<^ML>\<open>try\<close> and \<^ML>\<open>can\<close> above,
       
  1213   but with special treatment of the interrupt state of the underlying ML
       
  1214   thread. There are also variants to support \<^verbatim>\<open>try_catch\<close> and \<^verbatim>\<open>try_finally\<close>
       
  1215   blocks similar to Scala.
       
  1216 
       
  1217   The substructure of the embedded argument supports the following syntax
       
  1218   variants:
       
  1219 
       
  1220   \<^rail>\<open>
       
  1221     @{syntax_def try_catch}: @{syntax expr} @'catch' @{syntax handler};
       
  1222     @{syntax_def try_finally}: @{syntax expr} @'finally' @{syntax cleanup};
       
  1223     @{syntax_def try}: @{syntax expr};
       
  1224     @{syntax_def can}: @{syntax expr}
       
  1225   \<close>
       
  1226 
       
  1227   The @{syntax handler} of \<^verbatim>\<open>try_catch\<close> follows the syntax of \<^ML_text>\<open>fn\<close>
       
  1228   patterns, so it is similar to \<^ML_text>\<open>handle\<close>: the key difference is
       
  1229   that interrupts are always passed-through via \<^ML>\<open>Exn.reraise\<close>.
       
  1230 
       
  1231   The @{syntax cleanup} expression of \<^verbatim>\<open>try_finally\<close> is always invoked,
       
  1232   regardless of the overall exception result, and afterwards exceptions are
       
  1233   passed-through via \<^ML>\<open>Exn.reraise\<close>.
       
  1234 
       
  1235   Both the @{syntax handler} and @{syntax cleanup} are evaluated with further
       
  1236   interrupts disabled! These expressions should terminate promptly; timeouts
       
  1237   don't work here.
       
  1238 
       
  1239   \<^medskip>
       
  1240   Implementation details can be seen in \<^ML>\<open>Isabelle_Thread.try_catch\<close>,
       
  1241   \<^ML>\<open>Isabelle_Thread.try_finally\<close>, \<^ML>\<open>Isabelle_Thread.try\<close>, and
       
  1242   \<^ML>\<open>Isabelle_Thread.can\<close>, respectively. The ML antiquotations add
       
  1243   functional abstractions as required for these ``special forms'' of
       
  1244   Isabelle/ML.
  1207 
  1245 
  1208   \<^descr> \<open>@{assert}\<close> inlines a function \<^ML_type>\<open>bool -> unit\<close> that raises
  1246   \<^descr> \<open>@{assert}\<close> inlines a function \<^ML_type>\<open>bool -> unit\<close> that raises
  1209   \<^ML>\<open>Fail\<close> if the argument is \<^ML>\<open>false\<close>. Due to inlining the source
  1247   \<^ML>\<open>Fail\<close> if the argument is \<^ML>\<open>false\<close>. Due to inlining the source
  1210   position of failed assertions is included in the error output.
  1248   position of failed assertions is included in the error output.
  1211 
  1249 
  1212   \<^descr> \<open>@{undefined}\<close> inlines \<^verbatim>\<open>raise\<close>~\<^ML>\<open>Match\<close>, i.e.\ the ML program
  1250   \<^descr> \<open>@{undefined}\<close> inlines \<^verbatim>\<open>raise\<close>~\<^ML>\<open>Match\<close>, i.e.\ the ML program
  1213   behaves as in some function application of an undefined case.
  1251   behaves as in some function application of an undefined case.
  1214 \<close>
  1252 \<close>
  1215 
  1253 
  1216 text %mlex \<open>
  1254 text %mlex \<open>
  1217   We define a total version of division: any failures are swept under the
  1255 
       
  1256   We define total versions of division: any failures are swept under the
  1218   carpet and mapped to a default value. Thus division-by-zero becomes 0, but
  1257   carpet and mapped to a default value. Thus division-by-zero becomes 0, but
  1219   there could be other exceptions like overflow that produce the same result
  1258   there could be other exceptions like overflow that produce the same result.
  1220   (for unbounded integers this does not happen).
  1259 
       
  1260   For unbounded integers such side-errors do not happen, but it might still be
       
  1261   better to be explicit about exception patterns (second version below).
  1221 \<close>
  1262 \<close>
  1222 
  1263 
  1223 ML \<open>
  1264 ML \<open>
  1224   fun div_total x y = \<^try>\<open>x div y\<close> |> the_default 0;
  1265   fun div_total1 x y = \<^try>\<open>x div y catch _ => 0\<close>;
  1225 
  1266   fun div_total2 x y = \<^try>\<open>x div y catch Div => 0\<close>;
  1226   \<^assert> (div_total 1 0 = 0);
  1267 
       
  1268   \<^assert> (div_total1 1 0 = 0);
       
  1269   \<^assert> (div_total2 1 0 = 0);
  1227 \<close>
  1270 \<close>
  1228 
  1271 
  1229 text \<open>
  1272 text \<open>
  1230   The ML function \<^ML>\<open>undefined\<close> is defined in \<^file>\<open>~~/src/Pure/library.ML\<close>
  1273   The ML function \<^ML>\<open>undefined\<close> is defined in \<^file>\<open>~~/src/Pure/library.ML\<close>
  1231   as follows:
  1274   as follows:
  1908   See \<^file>\<open>~~/src/Pure/Concurrent/mailbox.ML\<close> how to implement a mailbox as
  1951   See \<^file>\<open>~~/src/Pure/Concurrent/mailbox.ML\<close> how to implement a mailbox as
  1909   synchronized variable over a purely functional list.
  1952   synchronized variable over a purely functional list.
  1910 \<close>
  1953 \<close>
  1911 
  1954 
  1912 
  1955 
  1913 section \<open>Managed evaluation\<close>
  1956 section \<open>Managed evaluation \label{sec:managed-eval}\<close>
  1914 
  1957 
  1915 text \<open>
  1958 text \<open>
  1916   Execution of Standard ML follows the model of strict functional evaluation
  1959   Execution of Standard ML follows the model of strict functional evaluation
  1917   with optional exceptions. Evaluation happens whenever some function is
  1960   with optional exceptions. Evaluation happens whenever some function is
  1918   applied to (sufficiently many) arguments. The result is either an explicit
  1961   applied to (sufficiently many) arguments. The result is either an explicit