87 \isacommand{oops} |
87 \isacommand{oops} |
88 \end{isabelle} |
88 \end{isabelle} |
89 \end{quote} |
89 \end{quote} |
90 |
90 |
91 However, both commands will only play minor roles in this tutorial (we will |
91 However, both commands will only play minor roles in this tutorial (we will |
92 always arrange that the ML-code is defined outside of proofs). |
92 always arrange that the ML-code is defined outside proofs). |
93 |
93 |
94 Once a portion of code is relatively stable, you usually want to export it |
94 Once a portion of code is relatively stable, you usually want to export it |
95 to a separate ML-file. Such files can then be included somewhere inside a |
95 to a separate ML-file. Such files can then be included somewhere inside a |
96 theory by using the command \isacommand{use}. For example |
96 theory by using the command \isacommand{use}. For example |
97 |
97 |
128 *} |
128 *} |
129 |
129 |
130 section {* Printing and Debugging\label{sec:printing} *} |
130 section {* Printing and Debugging\label{sec:printing} *} |
131 |
131 |
132 text {* |
132 text {* |
133 During development you might find it necessary to inspect some data in your |
133 During development you might find it necessary to inspect data in your |
134 code. This can be done in a ``quick-and-dirty'' fashion using the function |
134 code. This can be done in a ``quick-and-dirty'' fashion using the function |
135 @{ML_ind writeln in Output}. For example |
135 @{ML_ind writeln in Output}. For example |
136 |
136 |
137 @{ML_response_eq [display,gray] "writeln \"any string\"" "\"any string\"" with "(op =)"} |
137 @{ML_response_eq [display,gray] "writeln \"any string\"" "\"any string\"" with "(op =)"} |
138 |
138 |
154 output into a separate tracing buffer. For example: |
154 output into a separate tracing buffer. For example: |
155 |
155 |
156 @{ML_response_eq [display,gray] "tracing \"foo\"" "\"foo\"" with "(op =)"} |
156 @{ML_response_eq [display,gray] "tracing \"foo\"" "\"foo\"" with "(op =)"} |
157 |
157 |
158 It is also possible to redirect the ``channel'' where the string @{text |
158 It is also possible to redirect the ``channel'' where the string @{text |
159 "foo"} is printed to a separate file, e.g., to prevent ProofGeneral from |
159 "foo"} is printed to a separate file, e.g., in order to prevent ProofGeneral from |
160 choking on massive amounts of trace output. This redirection can be achieved |
160 choking on massive amounts of trace output. This redirection can be achieved |
161 with the code: |
161 with the code: |
162 *} |
162 *} |
163 |
163 |
164 ML{*val strip_specials = |
164 ML{*val strip_specials = |
217 Most often you want to inspect data of Isabelle's basic data |
217 Most often you want to inspect data of Isabelle's basic data |
218 structures, namely @{ML_type term}, @{ML_type cterm} and @{ML_type |
218 structures, namely @{ML_type term}, @{ML_type cterm} and @{ML_type |
219 thm}. Isabelle contains elaborate pretty-printing functions for printing |
219 thm}. Isabelle contains elaborate pretty-printing functions for printing |
220 them (see Section \ref{sec:pretty}), but for quick-and-dirty solutions they |
220 them (see Section \ref{sec:pretty}), but for quick-and-dirty solutions they |
221 are a bit unwieldy. One way to transform a term into a string is to use the |
221 are a bit unwieldy. One way to transform a term into a string is to use the |
222 function @{ML_ind string_of_term in Syntax} in the structure @{ML_struct |
222 function @{ML_ind string_of_term in Syntax} from the structure @{ML_struct |
223 Syntax}. For more convenience, we bind this function to the toplevel. |
223 Syntax}. For more convenience, we bind this function to the toplevel. |
224 *} |
224 *} |
225 |
225 |
226 ML{*val string_of_term = Syntax.string_of_term*} |
226 ML{*val string_of_term = Syntax.string_of_term*} |
227 |
227 |
252 |
252 |
253 ML{*fun string_of_terms ctxt ts = |
253 ML{*fun string_of_terms ctxt ts = |
254 commas (map (string_of_term ctxt) ts)*} |
254 commas (map (string_of_term ctxt) ts)*} |
255 |
255 |
256 text {* |
256 text {* |
257 You can also print out term together with type information. |
257 You can also print out terms together with typing information. |
258 This can be achieved by setting the reference @{ML_ind show_types in Syntax} |
258 For this you need to set the reference @{ML_ind show_types in Syntax} |
259 to @{ML true}. |
259 to @{ML true}. |
260 *} |
260 *} |
261 |
261 |
262 ML{*show_types := true*} |
262 ML{*show_types := true*} |
263 |
263 |
268 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
268 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
269 "(1::nat, x::'a)"} |
269 "(1::nat, x::'a)"} |
270 |
270 |
271 where @{text 1} and @{text x} are displayed with their inferred type. |
271 where @{text 1} and @{text x} are displayed with their inferred type. |
272 Even more type information can be printed by setting |
272 Even more type information can be printed by setting |
273 @{ML_ind show_all_types in Syntax} to @{ML true}. We obtain then |
273 the reference @{ML_ind show_all_types in Syntax} to @{ML true}. |
|
274 We obtain then |
274 *} |
275 *} |
275 (*<*)ML %linenos {*show_all_types := true*} |
276 (*<*)ML %linenos {*show_all_types := true*} |
276 (*>*) |
277 (*>*) |
277 text {* |
278 text {* |
278 @{ML_response_fake [display, gray] |
279 @{ML_response_fake [display, gray] |
279 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
280 "tracing (string_of_term @{context} @{term \"(1::nat, x)\"})" |
280 "(Pair::nat \<Rightarrow> 'a \<Rightarrow> nat \<times> 'a) (1::nat) (x::'a)"} |
281 "(Pair::nat \<Rightarrow> 'a \<Rightarrow> nat \<times> 'a) (1::nat) (x::'a)"} |
281 |
282 |
|
283 where @{term Pair} is the term-constructor for products. |
282 Other references that influence printing are @{ML_ind show_brackets in Syntax} |
284 Other references that influence printing are @{ML_ind show_brackets in Syntax} |
283 and @{ML_ind show_sorts in Syntax}. |
285 and @{ML_ind show_sorts in Syntax}. |
284 *} |
286 *} |
285 (*<*)ML %linenos {*show_types := false; show_all_types := false*} |
287 (*<*)ML %linenos {*show_types := false; show_all_types := false*} |
286 (*>*) |
288 (*>*) |
334 |
336 |
335 fun string_of_thm_no_vars ctxt thm = |
337 fun string_of_thm_no_vars ctxt thm = |
336 string_of_term ctxt (prop_of (no_vars ctxt thm))*} |
338 string_of_term ctxt (prop_of (no_vars ctxt thm))*} |
337 |
339 |
338 text {* |
340 text {* |
339 Theorem @{thm [source] conjI} is now printed as follows: |
341 With this function, theorem @{thm [source] conjI} is now printed as follows: |
340 |
342 |
341 @{ML_response_fake [display, gray] |
343 @{ML_response_fake [display, gray] |
342 "tracing (string_of_thm_no_vars @{context} @{thm conjI})" |
344 "tracing (string_of_thm_no_vars @{context} @{thm conjI})" |
343 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
345 "\<lbrakk>P; Q\<rbrakk> \<Longrightarrow> P \<and> Q"} |
344 |
346 |
357 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
359 @{ML_type string}s are implemented in @{ML_file "Pure/Syntax/syntax.ML"}. |
358 The references that change the printing information are declared in |
360 The references that change the printing information are declared in |
359 @{ML_file "Pure/Syntax/printer.ML"}. |
361 @{ML_file "Pure/Syntax/printer.ML"}. |
360 \end{readmore} |
362 \end{readmore} |
361 |
363 |
362 Note that when printing out several ``parcels'' of information that |
364 Note that for printing out several ``parcels'' of information that |
363 semantically belong together, like a warning message consisting of |
365 semantically belong together, like a warning message consisting of |
364 a term and its type, you should try to keep this information together in a |
366 a term and its type, you should try to keep this information together in a |
365 single string. Therefore do \emph{not} print out information as |
367 single string. Therefore do \emph{not} print out information as |
366 |
368 |
367 @{ML_response_fake [display,gray] |
369 @{ML_response_fake [display,gray] |
376 "tracing (\"First half,\" ^ \"\\n\" ^ \"and second half.\")" |
378 "tracing (\"First half,\" ^ \"\\n\" ^ \"and second half.\")" |
377 "First half, |
379 "First half, |
378 and second half."} |
380 and second half."} |
379 |
381 |
380 To ease this kind of string manipulations, there are a number |
382 To ease this kind of string manipulations, there are a number |
381 of library functions. For example, the function @{ML_ind cat_lines in Library} |
383 of library functions in Isabelle. For example, the function |
382 concatenates a list of strings and inserts newlines. |
384 @{ML_ind cat_lines in Library} concatenates a list of strings |
|
385 and inserts newlines in between each element. |
383 |
386 |
384 @{ML_response [display, gray] |
387 @{ML_response [display, gray] |
385 "cat_lines [\"foo\", \"bar\"]" |
388 "cat_lines [\"foo\", \"bar\"]" |
386 "\"foo\\nbar\""} |
389 "\"foo\\nbar\""} |
387 |
390 |
388 Section \ref{sec:pretty} will also explain the infrastructure of Isabelle |
391 Section \ref{sec:pretty} will also explain the infrastructure that Isabelle |
389 that helps with more elaborate pretty printing. |
392 provides for more elaborate pretty printing. |
390 |
393 |
391 \begin{readmore} |
394 \begin{readmore} |
392 Most of the basic string functions of Isabelle are defined in |
395 Most of the basic string functions of Isabelle are defined in |
393 @{ML_file "Pure/library.ML"}. |
396 @{ML_file "Pure/library.ML"}. |
394 \end{readmore} |
397 \end{readmore} |
506 avoiding the given @{text f}; the list of name-type pairs is turned into a |
509 avoiding the given @{text f}; the list of name-type pairs is turned into a |
507 list of variable terms in Line 6, which in the last line is applied by the |
510 list of variable terms in Line 6, which in the last line is applied by the |
508 function @{ML_ind list_comb in Term} to the term. In this last step we have |
511 function @{ML_ind list_comb in Term} to the term. In this last step we have |
509 to use the function @{ML_ind curry in Library}, because @{ML list_comb} |
512 to use the function @{ML_ind curry in Library}, because @{ML list_comb} |
510 expects the function and the variables list as a pair. |
513 expects the function and the variables list as a pair. |
|
514 |
511 Functions like @{ML apply_fresh_args} are often needed when constructing |
515 Functions like @{ML apply_fresh_args} are often needed when constructing |
512 terms with fresh variables. The |
516 terms with fresh variables. The |
513 infrastructure helps tremendously to avoid any name clashes. Consider for |
517 infrastructure helps tremendously to avoid any name clashes. Consider for |
514 example: |
518 example: |
515 |
519 |
529 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
533 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
530 It can be used to define the following function |
534 It can be used to define the following function |
531 *} |
535 *} |
532 |
536 |
533 ML{*val inc_by_six = |
537 ML{*val inc_by_six = |
534 (fn x => x + 1) |
538 (fn x => x + 1) #> |
535 #> (fn x => x + 2) |
539 (fn x => x + 2) #> |
536 #> (fn x => x + 3)*} |
540 (fn x => x + 3)*} |
537 |
541 |
538 text {* |
542 text {* |
539 which is the function composed of first the increment-by-one function and then |
543 which is the function composed of first the increment-by-one function and then |
540 increment-by-two, followed by increment-by-three. Again, the reverse function |
544 increment-by-two, followed by increment-by-three. Again, the reverse function |
541 composition allows you to read the code top-down. |
545 composition allows you to read the code top-down. |