91 text \<open> |
91 text \<open> |
92 During development you might find it necessary to inspect data in your |
92 During development you might find it necessary to inspect data in your |
93 code. This can be done in a ``quick-and-dirty'' fashion using the function |
93 code. This can be done in a ``quick-and-dirty'' fashion using the function |
94 @{ML_ind writeln in Output}. For example |
94 @{ML_ind writeln in Output}. For example |
95 |
95 |
96 @{ML_matchresult_fake [display,gray] "writeln \"any string\"" "\"any string\""} |
96 @{ML_matchresult_fake [display,gray] \<open>writeln "any string"\<close> \<open>"any string"\<close>} |
97 |
97 |
98 will print out @{text [quotes] "any string"}. |
98 will print out @{text [quotes] "any string"}. |
99 This function expects a string as argument. If you develop under |
99 This function expects a string as argument. If you develop under |
100 PolyML, then there is a convenient, though again ``quick-and-dirty'', method |
100 PolyML, then there is a convenient, though again ``quick-and-dirty'', method |
101 for converting values into strings, namely the antiquotation |
101 for converting values into strings, namely the antiquotation |
108 |
108 |
109 You can print out error messages with the function @{ML_ind error in Library}; |
109 You can print out error messages with the function @{ML_ind error in Library}; |
110 for example: |
110 for example: |
111 |
111 |
112 @{ML_matchresult_fake [display,gray] |
112 @{ML_matchresult_fake [display,gray] |
113 "if 0 = 1 then true else (error \"foo\")" |
113 \<open>if 0 = 1 then true else (error "foo")\<close> |
114 "*** foo |
114 \<open>*** foo |
115 ***"} |
115 ***\<close>} |
116 |
116 |
117 This function raises the exception \<open>ERROR\<close>, which will then |
117 This function raises the exception \<open>ERROR\<close>, which will then |
118 be displayed by the infrastructure indicating that it is an error by |
118 be displayed by the infrastructure indicating that it is an error by |
119 painting the output red. Note that this exception is meant |
119 painting the output red. Note that this exception is meant |
120 for ``user-level'' error messages seen by the ``end-user''. |
120 for ``user-level'' error messages seen by the ``end-user''. |
158 |
158 |
159 text \<open> |
159 text \<open> |
160 Now by using this context @{ML pretty_term} prints out |
160 Now by using this context @{ML pretty_term} prints out |
161 |
161 |
162 @{ML_matchresult_fake [display, gray] |
162 @{ML_matchresult_fake [display, gray] |
163 "pwriteln (pretty_term show_types_ctxt @{term \"(1::nat, x)\"})" |
163 \<open>pwriteln (pretty_term show_types_ctxt @{term "(1::nat, x)"})\<close> |
164 "(1::nat, x::'a)"} |
164 \<open>(1::nat, x::'a)\<close>} |
165 |
165 |
166 where \<open>1\<close> and \<open>x\<close> are displayed with their inferred types. |
166 where \<open>1\<close> and \<open>x\<close> are displayed with their inferred types. |
167 Other configuration values that influence |
167 Other configuration values that influence |
168 printing of terms include |
168 printing of terms include |
169 |
169 |
202 For example, the theorem |
202 For example, the theorem |
203 @{thm [source] conjI} shown below can be used for any (typable) |
203 @{thm [source] conjI} shown below can be used for any (typable) |
204 instantiation of \<open>?P\<close> and \<open>?Q\<close>. |
204 instantiation of \<open>?P\<close> and \<open>?Q\<close>. |
205 |
205 |
206 @{ML_matchresult_fake [display, gray] |
206 @{ML_matchresult_fake [display, gray] |
207 "pwriteln (pretty_thm @{context} @{thm conjI})" |
207 \<open>pwriteln (pretty_thm @{context} @{thm conjI})\<close> |
208 "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"} |
208 \<open>\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\<close>} |
209 |
209 |
210 However, to improve the readability when printing theorems, we |
210 However, to improve the readability when printing theorems, we |
211 can switch off the question marks as follows: |
211 can switch off the question marks as follows: |
212 \<close> |
212 \<close> |
213 |
213 |
263 together, like a warning message consisting of a term and its type, you |
263 together, like a warning message consisting of a term and its type, you |
264 should try to print these parcels together in a single string. Therefore do |
264 should try to print these parcels together in a single string. Therefore do |
265 \emph{not} print out information as |
265 \emph{not} print out information as |
266 |
266 |
267 @{ML_matchresult_fake [display,gray] |
267 @{ML_matchresult_fake [display,gray] |
268 "pwriteln (Pretty.str \"First half,\"); |
268 \<open>pwriteln (Pretty.str "First half,"); |
269 pwriteln (Pretty.str \"and second half.\")" |
269 pwriteln (Pretty.str "and second half.")\<close> |
270 "First half, |
270 \<open>First half, |
271 and second half."} |
271 and second half.\<close>} |
272 |
272 |
273 but as a single string with appropriate formatting. For example |
273 but as a single string with appropriate formatting. For example |
274 |
274 |
275 @{ML_matchresult_fake [display,gray] |
275 @{ML_matchresult_fake [display,gray] |
276 "pwriteln (Pretty.str (\"First half,\" ^ \"\\n\" ^ \"and second half.\"))" |
276 \<open>pwriteln (Pretty.str ("First half," ^ "\\n" ^ "and second half."))\<close> |
277 "First half, |
277 \<open>First half, |
278 and second half."} |
278 and second half.\<close>} |
279 |
279 |
280 To ease this kind of string manipulations, there are a number |
280 To ease this kind of string manipulations, there are a number |
281 of library functions in Isabelle. For example, the function |
281 of library functions in Isabelle. For example, the function |
282 @{ML_ind cat_lines in Library} concatenates a list of strings |
282 @{ML_ind cat_lines in Library} concatenates a list of strings |
283 and inserts newlines in between each element. |
283 and inserts newlines in between each element. |
284 |
284 |
285 @{ML_matchresult_fake [display, gray] |
285 @{ML_matchresult_fake [display, gray] |
286 "pwriteln (Pretty.str (cat_lines [\"foo\", \"bar\"]))" |
286 \<open>pwriteln (Pretty.str (cat_lines ["foo", "bar"]))\<close> |
287 "foo |
287 \<open>foo |
288 bar"} |
288 bar\<close>} |
289 |
289 |
290 Section \ref{sec:pretty} will explain the infrastructure that Isabelle |
290 Section \ref{sec:pretty} will explain the infrastructure that Isabelle |
291 provides for more elaborate pretty printing. |
291 provides for more elaborate pretty printing. |
292 |
292 |
293 \begin{readmore} |
293 \begin{readmore} |
381 |> map Free |
381 |> map Free |
382 |> curry list_comb f\<close> |
382 |> curry list_comb f\<close> |
383 |
383 |
384 text \<open> |
384 text \<open> |
385 This function takes a term and a context as arguments. If the term is of function |
385 This function takes a term and a context as arguments. If the term is of function |
386 type, then @{ML "apply_fresh_args"} returns the term with distinct variables |
386 type, then @{ML \<open>apply_fresh_args\<close>} returns the term with distinct variables |
387 applied to it. For example, below three variables are applied to the term |
387 applied to it. For example, below three variables are applied to the term |
388 @{term [show_types] "P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool"}: |
388 @{term [show_types] "P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool"}: |
389 |
389 |
390 @{ML_matchresult_fake [display,gray] |
390 @{ML_matchresult_fake [display,gray] |
391 "let |
391 \<open>let |
392 val trm = @{term \"P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool\"} |
392 val trm = @{term "P::nat \<Rightarrow> int \<Rightarrow> unit \<Rightarrow> bool"} |
393 val ctxt = @{context} |
393 val ctxt = @{context} |
394 in |
394 in |
395 apply_fresh_args trm ctxt |
395 apply_fresh_args trm ctxt |
396 |> pretty_term ctxt |
396 |> pretty_term ctxt |
397 |> pwriteln |
397 |> pwriteln |
398 end" |
398 end\<close> |
399 "P z za zb"} |
399 \<open>P z za zb\<close>} |
400 |
400 |
401 You can read off this behaviour from how @{ML apply_fresh_args} is coded: in |
401 You can read off this behaviour from how @{ML apply_fresh_args} is coded: in |
402 Line 2, the function @{ML_ind fastype_of in Term} calculates the type of the |
402 Line 2, the function @{ML_ind fastype_of in Term} calculates the type of the |
403 term; @{ML_ind binder_types in Term} in the next line produces the list of |
403 term; @{ML_ind binder_types in Term} in the next line produces the list of |
404 argument types (in the case above the list \<open>[nat, int, unit]\<close>); Line |
404 argument types (in the case above the list \<open>[nat, int, unit]\<close>); Line |
413 Functions like @{ML apply_fresh_args} are often needed when constructing |
413 Functions like @{ML apply_fresh_args} are often needed when constructing |
414 terms involving fresh variables. For this the infrastructure helps |
414 terms involving fresh variables. For this the infrastructure helps |
415 tremendously to avoid any name clashes. Consider for example: |
415 tremendously to avoid any name clashes. Consider for example: |
416 |
416 |
417 @{ML_matchresult_fake [display,gray] |
417 @{ML_matchresult_fake [display,gray] |
418 "let |
418 \<open>let |
419 val trm = @{term \"za::'a \<Rightarrow> 'b \<Rightarrow> 'c\"} |
419 val trm = @{term "za::'a \<Rightarrow> 'b \<Rightarrow> 'c"} |
420 val ctxt = @{context} |
420 val ctxt = @{context} |
421 in |
421 in |
422 apply_fresh_args trm ctxt |
422 apply_fresh_args trm ctxt |
423 |> pretty_term ctxt |
423 |> pretty_term ctxt |
424 |> pwriteln |
424 |> pwriteln |
425 end" |
425 end\<close> |
426 "za z zb"} |
426 \<open>za z zb\<close>} |
427 |
427 |
428 where the \<open>za\<close> is correctly avoided. |
428 where the \<open>za\<close> is correctly avoided. |
429 |
429 |
430 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
430 The combinator @{ML_ind "#>" in Basics} is the reverse function composition. |
431 It can be used to define the following function |
431 It can be used to define the following function |
442 function composition allows you to read the code top-down. This combinator |
442 function composition allows you to read the code top-down. This combinator |
443 is often used for setup functions inside the |
443 is often used for setup functions inside the |
444 \isacommand{setup}- or \isacommand{local\_setup}-command. These functions |
444 \isacommand{setup}- or \isacommand{local\_setup}-command. These functions |
445 have to be of type @{ML_type "theory -> theory"}, respectively |
445 have to be of type @{ML_type "theory -> theory"}, respectively |
446 @{ML_type "local_theory -> local_theory"}. More than one such setup function |
446 @{ML_type "local_theory -> local_theory"}. More than one such setup function |
447 can be composed with @{ML "#>"}. Consider for example the following code, |
447 can be composed with @{ML \<open>#>\<close>}. Consider for example the following code, |
448 where we store the theorems @{thm [source] conjI}, @{thm [source] conjunct1} |
448 where we store the theorems @{thm [source] conjI}, @{thm [source] conjunct1} |
449 and @{thm [source] conjunct2} under alternative names. |
449 and @{thm [source] conjunct2} under alternative names. |
450 \<close> |
450 \<close> |
451 |
451 |
452 local_setup %graylinenos \<open> |
452 local_setup %graylinenos \<open> |
461 text \<open> |
461 text \<open> |
462 The function @{ML_text "my_note"} in line 3 is just a wrapper for the function |
462 The function @{ML_text "my_note"} in line 3 is just a wrapper for the function |
463 @{ML_ind note in Local_Theory} in the structure @{ML_structure Local_Theory}; |
463 @{ML_ind note in Local_Theory} in the structure @{ML_structure Local_Theory}; |
464 it stores a theorem under a name. |
464 it stores a theorem under a name. |
465 In lines 5 to 6 we call this function to give alternative names for the three |
465 In lines 5 to 6 we call this function to give alternative names for the three |
466 theorems. The point of @{ML "#>"} is that you can sequence such function calls. |
466 theorems. The point of @{ML \<open>#>\<close>} is that you can sequence such function calls. |
467 |
467 |
468 The remaining combinators we describe in this section add convenience for |
468 The remaining combinators we describe in this section add convenience for |
469 the ``waterfall method'' of writing functions. The combinator @{ML_ind tap |
469 the ``waterfall method'' of writing functions. The combinator @{ML_ind tap |
470 in Basics} allows you to get hold of an intermediate result (to do some |
470 in Basics} allows you to get hold of an intermediate result (to do some |
471 side-calculations or print out an intermediate result, for instance). The |
471 side-calculations or print out an intermediate result, for instance). The |
499 x |> `(fn x => x + 1) |
499 x |> `(fn x => x + 1) |
500 |> (fn (x, y) => (x, y + 1))\<close> |
500 |> (fn (x, y) => (x, y + 1))\<close> |
501 |
501 |
502 text \<open> |
502 text \<open> |
503 which takes \<open>x\<close> as argument, and then increments \<open>x\<close>, but also keeps |
503 which takes \<open>x\<close> as argument, and then increments \<open>x\<close>, but also keeps |
504 \<open>x\<close>. The intermediate result is therefore the pair @{ML "(x + 1, x)" |
504 \<open>x\<close>. The intermediate result is therefore the pair @{ML \<open>(x + 1, x)\<close> |
505 for x}. After that, the function increments the right-hand component of the |
505 for x}. After that, the function increments the right-hand component of the |
506 pair. So finally the result will be @{ML "(x + 1, x + 1)" for x}. |
506 pair. So finally the result will be @{ML \<open>(x + 1, x + 1)\<close> for x}. |
507 |
507 |
508 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
508 The combinators @{ML_ind "|>>" in Basics} and @{ML_ind "||>" in Basics} are |
509 defined for functions manipulating pairs. The first applies the function to |
509 defined for functions manipulating pairs. The first applies the function to |
510 the first component of the pair, defined as |
510 the first component of the pair, defined as |
511 \<close> |
511 \<close> |
520 |
520 |
521 text \<open> |
521 text \<open> |
522 These two functions can, for example, be used to avoid explicit \<open>lets\<close> for |
522 These two functions can, for example, be used to avoid explicit \<open>lets\<close> for |
523 intermediate values in functions that return pairs. As an example, suppose you |
523 intermediate values in functions that return pairs. As an example, suppose you |
524 want to separate a list of integers into two lists according to a |
524 want to separate a list of integers into two lists according to a |
525 threshold. If the threshold is @{ML "5"}, the list @{ML "[1,6,2,5,3,4]"} |
525 threshold. If the threshold is @{ML \<open>5\<close>}, the list @{ML \<open>[1,6,2,5,3,4]\<close>} |
526 should be separated as @{ML "([1,2,3,4], [6,5])"}. Such a function can be |
526 should be separated as @{ML \<open>([1,2,3,4], [6,5])\<close>}. Such a function can be |
527 implemented as |
527 implemented as |
528 \<close> |
528 \<close> |
529 |
529 |
530 ML %grayML\<open>fun separate i [] = ([], []) |
530 ML %grayML\<open>fun separate i [] = ([], []) |
531 | separate i (x::xs) = |
531 | separate i (x::xs) = |
535 if i <= x then (los, x::grs) else (x::los, grs) |
535 if i <= x then (los, x::grs) else (x::los, grs) |
536 end\<close> |
536 end\<close> |
537 |
537 |
538 text \<open> |
538 text \<open> |
539 where the return value of the recursive call is bound explicitly to |
539 where the return value of the recursive call is bound explicitly to |
540 the pair @{ML "(los, grs)" for los grs}. However, this function |
540 the pair @{ML \<open>(los, grs)\<close> for los grs}. However, this function |
541 can be implemented more concisely as |
541 can be implemented more concisely as |
542 \<close> |
542 \<close> |
543 |
543 |
544 ML %grayML\<open>fun separate _ [] = ([], []) |
544 ML %grayML\<open>fun separate _ [] = ([], []) |
545 | separate i (x::xs) = |
545 | separate i (x::xs) = |
586 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
586 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
587 @{ML ||>>} operates on pairs). Each of the next three lines just increment |
587 @{ML ||>>} operates on pairs). Each of the next three lines just increment |
588 the value by one, but also nest the intermediate results to the left. For example |
588 the value by one, but also nest the intermediate results to the left. For example |
589 |
589 |
590 @{ML_matchresult [display,gray] |
590 @{ML_matchresult [display,gray] |
591 "acc_incs 1" |
591 \<open>acc_incs 1\<close> |
592 "((((\"\", 1), 2), 3), 4)"} |
592 \<open>(((("", 1), 2), 3), 4)\<close>} |
593 |
593 |
594 You can continue this chain with: |
594 You can continue this chain with: |
595 |
595 |
596 @{ML_matchresult [display,gray] |
596 @{ML_matchresult [display,gray] |
597 "acc_incs 1 ||>> (fn x => (x, x + 2))" |
597 \<open>acc_incs 1 ||>> (fn x => (x, x + 2))\<close> |
598 "(((((\"\", 1), 2), 3), 4), 6)"} |
598 \<open>((((("", 1), 2), 3), 4), 6)\<close>} |
599 |
599 |
600 An example where this combinator is useful is as follows |
600 An example where this combinator is useful is as follows |
601 |
601 |
602 @{ML_matchresult_fake [display, gray] |
602 @{ML_matchresult_fake [display, gray] |
603 "let |
603 \<open>let |
604 val ((names1, names2), _) = |
604 val ((names1, names2), _) = |
605 @{context} |
605 @{context} |
606 |> Variable.variant_fixes (replicate 4 \"x\") |
606 |> Variable.variant_fixes (replicate 4 "x") |
607 ||>> Variable.variant_fixes (replicate 5 \"x\") |
607 ||>> Variable.variant_fixes (replicate 5 "x") |
608 in |
608 in |
609 (names1, names2) |
609 (names1, names2) |
610 end" |
610 end\<close> |
611 "([\"x\", \"xa\", \"xb\", \"xc\"], [\"xd\", \"xe\", \"xf\", \"xg\", \"xh\"])"} |
611 \<open>(["x", "xa", "xb", "xc"], ["xd", "xe", "xf", "xg", "xh"])\<close>} |
612 |
612 |
613 Its purpose is to create nine variants of the string @{ML "\"x\""} so |
613 Its purpose is to create nine variants of the string @{ML \<open>"x"\<close>} so |
614 that no variant will clash with another. Suppose for some reason we want |
614 that no variant will clash with another. Suppose for some reason we want |
615 to bind four variants to the lists @{ML_text "name1"} and the |
615 to bind four variants to the lists @{ML_text "name1"} and the |
616 rest to @{ML_text "name2"}. In order to obtain non-clashing |
616 rest to @{ML_text "name2"}. In order to obtain non-clashing |
617 variants we have to thread the context through the function calls |
617 variants we have to thread the context through the function calls |
618 (the context records which variants have been previously created). |
618 (the context records which variants have been previously created). |
619 For the first call we can use @{ML "|>"}, but in the |
619 For the first call we can use @{ML \<open>|>\<close>}, but in the |
620 second and any further call to @{ML_ind variant_fixes in Variable} we |
620 second and any further call to @{ML_ind variant_fixes in Variable} we |
621 have to use @{ML "||>>"} in order to account for the result(s) |
621 have to use @{ML \<open>||>>\<close>} in order to account for the result(s) |
622 obtained by previous calls. |
622 obtained by previous calls. |
623 |
623 |
624 A more realistic example for this combinator is the following code |
624 A more realistic example for this combinator is the following code |
625 \<close> |
625 \<close> |
626 |
626 |
638 information about the definitions---the function @{ML_ind define in Local_Defs} returns |
638 information about the definitions---the function @{ML_ind define in Local_Defs} returns |
639 both as pairs. We can use this information for example to print out the definiens and |
639 both as pairs. We can use this information for example to print out the definiens and |
640 the theorem corresponding to the definitions. For example for the first definition: |
640 the theorem corresponding to the definitions. For example for the first definition: |
641 |
641 |
642 @{ML_matchresult_fake [display, gray] |
642 @{ML_matchresult_fake [display, gray] |
643 "let |
643 \<open>let |
644 val (one_trm, (_, one_thm)) = one_def |
644 val (one_trm, (_, one_thm)) = one_def |
645 in |
645 in |
646 pwriteln (pretty_term ctxt' one_trm); |
646 pwriteln (pretty_term ctxt' one_trm); |
647 pwriteln (pretty_thm ctxt' one_thm) |
647 pwriteln (pretty_thm ctxt' one_thm) |
648 end" |
648 end\<close> |
649 "One |
649 \<open>One |
650 One \<equiv> 1"} |
650 One \<equiv> 1\<close>} |
651 Recall that @{ML "|>"} is the reverse function application. Recall also that |
651 Recall that @{ML \<open>|>\<close>} is the reverse function application. Recall also that |
652 the related reverse function composition is @{ML "#>"}. In fact all the |
652 the related reverse function composition is @{ML \<open>#>\<close>}. In fact all the |
653 combinators @{ML "|->"}, @{ML "|>>"} , @{ML "||>"} and @{ML "||>>"} |
653 combinators @{ML \<open>|->\<close>}, @{ML \<open>|>>\<close>} , @{ML \<open>||>\<close>} and @{ML \<open>||>>\<close>} |
654 described above have related combinators for function composition, namely |
654 described above have related combinators for function composition, namely |
655 @{ML_ind "#->" in Basics}, @{ML_ind "#>>" in Basics}, @{ML_ind "##>" in |
655 @{ML_ind "#->" in Basics}, @{ML_ind "#>>" in Basics}, @{ML_ind "##>" in |
656 Basics} and @{ML_ind "##>>" in Basics}. Using @{ML "#->"}, for example, the |
656 Basics} and @{ML_ind "##>>" in Basics}. Using @{ML \<open>#->\<close>}, for example, the |
657 function \<open>double\<close> can also be written as: |
657 function \<open>double\<close> can also be written as: |
658 \<close> |
658 \<close> |
659 |
659 |
660 ML %grayML\<open>val double = |
660 ML %grayML\<open>val double = |
661 (fn x => (x, x)) #-> |
661 (fn x => (x, x)) #-> |
665 text \<open> |
665 text \<open> |
666 When using combinators for writing functions in waterfall fashion, it is |
666 When using combinators for writing functions in waterfall fashion, it is |
667 sometimes necessary to do some ``plumbing'' in order to fit functions |
667 sometimes necessary to do some ``plumbing'' in order to fit functions |
668 together. We have already seen such plumbing in the function @{ML |
668 together. We have already seen such plumbing in the function @{ML |
669 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
669 apply_fresh_args}, where @{ML curry} is needed for making the function @{ML |
670 list_comb}, which works over pairs, to fit with the combinator @{ML "|>"}. Such |
670 list_comb}, which works over pairs, to fit with the combinator @{ML \<open>|>\<close>}. Such |
671 plumbing is also needed in situations where a function operates over lists, |
671 plumbing is also needed in situations where a function operates over lists, |
672 but one calculates only with a single element. An example is the function |
672 but one calculates only with a single element. An example is the function |
673 @{ML_ind check_terms in Syntax}, whose purpose is to simultaneously type-check |
673 @{ML_ind check_terms in Syntax}, whose purpose is to simultaneously type-check |
674 a list of terms. Consider the code: |
674 a list of terms. Consider the code: |
675 |
675 |
676 @{ML_matchresult_fake [display, gray] |
676 @{ML_matchresult_fake [display, gray] |
677 "let |
677 \<open>let |
678 val ctxt = @{context} |
678 val ctxt = @{context} |
679 in |
679 in |
680 map (Syntax.parse_term ctxt) [\"m + n\", \"m * n\", \"m - (n::nat)\"] |
680 map (Syntax.parse_term ctxt) ["m + n", "m * n", "m - (n::nat)"] |
681 |> Syntax.check_terms ctxt |
681 |> Syntax.check_terms ctxt |
682 |> pretty_terms ctxt |
682 |> pretty_terms ctxt |
683 |> pwriteln |
683 |> pwriteln |
684 end" |
684 end\<close> |
685 "m + n, m * n, m - n"} |
685 \<open>m + n, m * n, m - n\<close>} |
686 \<close> |
686 \<close> |
687 |
687 |
688 text \<open> |
688 text \<open> |
689 In this example we obtain three terms (using the function |
689 In this example we obtain three terms (using the function |
690 @{ML_ind parse_term in Syntax}) whose variables \<open>m\<close> and \<open>n\<close> |
690 @{ML_ind parse_term in Syntax}) whose variables \<open>m\<close> and \<open>n\<close> |
693 @{ML_ind singleton in Library}.\footnote{There is already a function @{ML check_term in |
693 @{ML_ind singleton in Library}.\footnote{There is already a function @{ML check_term in |
694 Syntax} in the file @{ML_file "Pure/Syntax/syntax.ML"} that is implemented |
694 Syntax} in the file @{ML_file "Pure/Syntax/syntax.ML"} that is implemented |
695 in terms of @{ML singleton} and @{ML check_terms in Syntax}.} For example |
695 in terms of @{ML singleton} and @{ML check_terms in Syntax}.} For example |
696 |
696 |
697 @{ML_matchresult_fake [display, gray, linenos] |
697 @{ML_matchresult_fake [display, gray, linenos] |
698 "let |
698 \<open>let |
699 val ctxt = @{context} |
699 val ctxt = @{context} |
700 in |
700 in |
701 Syntax.parse_term ctxt \"m - (n::nat)\" |
701 Syntax.parse_term ctxt "m - (n::nat)" |
702 |> singleton (Syntax.check_terms ctxt) |
702 |> singleton (Syntax.check_terms ctxt) |
703 |> pretty_term ctxt |
703 |> pretty_term ctxt |
704 |> pwriteln |
704 |> pwriteln |
705 end" |
705 end\<close> |
706 "m - n"} |
706 \<open>m - n\<close>} |
707 |
707 |
708 where in Line 5, the function operating over lists fits with the |
708 where in Line 5, the function operating over lists fits with the |
709 single term generated in Line 4. |
709 single term generated in Line 4. |
710 |
710 |
711 \begin{readmore} |
711 \begin{readmore} |
741 except in Appendix \ref{rec:docantiquotations} where we show how to |
741 except in Appendix \ref{rec:docantiquotations} where we show how to |
742 implement your own document antiquotations.} Syntactically antiquotations |
742 implement your own document antiquotations.} Syntactically antiquotations |
743 are indicated by the @{ML_text @}-sign followed by text wrapped in \<open>{\<dots>}\<close>. For example, one can print out the name of the current theory with |
743 are indicated by the @{ML_text @}-sign followed by text wrapped in \<open>{\<dots>}\<close>. For example, one can print out the name of the current theory with |
744 the code |
744 the code |
745 |
745 |
746 @{ML_matchresult [display,gray] "Context.theory_name @{theory}" "\"First_Steps\""} |
746 @{ML_matchresult [display,gray] \<open>Context.theory_name @{theory}\<close> \<open>"First_Steps"\<close>} |
747 |
747 |
748 where \<open>@{theory}\<close> is an antiquotation that is substituted with the |
748 where \<open>@{theory}\<close> is an antiquotation that is substituted with the |
749 current theory (remember that we assumed we are inside the theory |
749 current theory (remember that we assumed we are inside the theory |
750 \<open>First_Steps\<close>). The name of this theory can be extracted using |
750 \<open>First_Steps\<close>). The name of this theory can be extracted using |
751 the function @{ML_ind theory_name in Context}. |
751 the function @{ML_ind theory_name in Context}. |
770 \ref{chp:advanced}.) A context is for example needed to use the |
770 \ref{chp:advanced}.) A context is for example needed to use the |
771 function @{ML print_abbrevs in Proof_Context} that list of all currently |
771 function @{ML print_abbrevs in Proof_Context} that list of all currently |
772 defined abbreviations. For example |
772 defined abbreviations. For example |
773 |
773 |
774 @{ML_matchresult_fake [display, gray] |
774 @{ML_matchresult_fake [display, gray] |
775 "Proof_Context.print_abbrevs false @{context}" |
775 \<open>Proof_Context.print_abbrevs false @{context}\<close> |
776 "\<dots> |
776 \<open>\<dots> |
777 INTER \<equiv> INFI |
777 INTER \<equiv> INFI |
778 Inter \<equiv> Inf |
778 Inter \<equiv> Inf |
779 \<dots>"} |
779 \<dots>\<close>} |
780 |
780 |
781 The precise output of course depends on the abbreviations that are |
781 The precise output of course depends on the abbreviations that are |
782 currently defined; this can change over time. |
782 currently defined; this can change over time. |
783 You can also use antiquotations to refer to proved theorems: |
783 You can also use antiquotations to refer to proved theorems: |
784 \<open>@{thm \<dots>}\<close> for a single theorem |
784 \<open>@{thm \<dots>}\<close> for a single theorem |
785 |
785 |
786 @{ML_matchresult_fake [display,gray] "@{thm allI}" "(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x"} |
786 @{ML_matchresult_fake [display,gray] \<open>@{thm allI}\<close> \<open>(\<And>x. ?P x) \<Longrightarrow> \<forall>x. ?P x\<close>} |
787 |
787 |
788 and \<open>@{thms \<dots>}\<close> for more than one |
788 and \<open>@{thms \<dots>}\<close> for more than one |
789 |
789 |
790 @{ML_matchresult_fake [display,gray] |
790 @{ML_matchresult_fake [display,gray] |
791 "@{thms conj_ac}" |
791 \<open>@{thms conj_ac}\<close> |
792 "(?P \<and> ?Q) = (?Q \<and> ?P) |
792 \<open>(?P \<and> ?Q) = (?Q \<and> ?P) |
793 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R) |
793 (?P \<and> ?Q \<and> ?R) = (?Q \<and> ?P \<and> ?R) |
794 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)"} |
794 ((?P \<and> ?Q) \<and> ?R) = (?P \<and> ?Q \<and> ?R)\<close>} |
795 |
795 |
796 The thm-antiquotations can also be used for manipulating theorems. For |
796 The thm-antiquotations can also be used for manipulating theorems. For |
797 example, if you need the version of the theorem @{thm [source] refl} that |
797 example, if you need the version of the theorem @{thm [source] refl} that |
798 has a meta-equality instead of an equality, you can write |
798 has a meta-equality instead of an equality, you can write |
799 |
799 |
800 @{ML_matchresult_fake [display,gray] |
800 @{ML_matchresult_fake [display,gray] |
801 "@{thm refl[THEN eq_reflection]}" |
801 \<open>@{thm refl[THEN eq_reflection]}\<close> |
802 "?x \<equiv> ?x"} |
802 \<open>?x \<equiv> ?x\<close>} |
803 |
803 |
804 The point of these antiquotations is that referring to theorems in this way |
804 The point of these antiquotations is that referring to theorems in this way |
805 makes your code independent from what theorems the user might have stored |
805 makes your code independent from what theorems the user might have stored |
806 under this name (this becomes especially important when you deal with |
806 under this name (this becomes especially important when you deal with |
807 theorem lists; see Section \ref{sec:storing}). |
807 theorem lists; see Section \ref{sec:storing}). |
839 information stored in the simpset, but here we are only interested in the names of the |
839 information stored in the simpset, but here we are only interested in the names of the |
840 simp-rules. Now you can feed in the current simpset into this function. |
840 simp-rules. Now you can feed in the current simpset into this function. |
841 The current simpset can be referred to using @{ML_ind simpset_of in Raw_Simplifier}. |
841 The current simpset can be referred to using @{ML_ind simpset_of in Raw_Simplifier}. |
842 |
842 |
843 @{ML_matchresult_fake [display,gray] |
843 @{ML_matchresult_fake [display,gray] |
844 "get_thm_names_from_ss @{context}" |
844 \<open>get_thm_names_from_ss @{context}\<close> |
845 "[\"Nat.of_nat_eq_id\", \"Int.of_int_eq_id\", \"Nat.One_nat_def\", \<dots>]"} |
845 \<open>["Nat.of_nat_eq_id", "Int.of_int_eq_id", "Nat.One_nat_def", \<dots>]\<close>} |
846 |
846 |
847 Again, this way of referencing simpsets makes you independent from additions |
847 Again, this way of referencing simpsets makes you independent from additions |
848 of lemmas to the simpset by the user, which can potentially cause loops in your |
848 of lemmas to the simpset by the user, which can potentially cause loops in your |
849 code. |
849 code. |
850 |
850 |
883 Proof_Context} (Line 5); the next two lines transform the term into a string |
883 Proof_Context} (Line 5); the next two lines transform the term into a string |
884 so that the ML-system can understand it. (All these functions will be explained |
884 so that the ML-system can understand it. (All these functions will be explained |
885 in more detail in later sections.) An example for this antiquotation is: |
885 in more detail in later sections.) An example for this antiquotation is: |
886 |
886 |
887 @{ML_matchresult_fake [display,gray] |
887 @{ML_matchresult_fake [display,gray] |
888 "@{term_pat \"Suc (?x::nat)\"}" |
888 \<open>@{term_pat "Suc (?x::nat)"}\<close> |
889 "Const (\"Suc\", \"nat \<Rightarrow> nat\") $ Var ((\"x\", 0), \"nat\")"} |
889 \<open>Const ("Suc", "nat \<Rightarrow> nat") $ Var (("x", 0), "nat")\<close>} |
890 |
890 |
891 which shows the internal representation of the term \<open>Suc ?x\<close>. Similarly |
891 which shows the internal representation of the term \<open>Suc ?x\<close>. Similarly |
892 we can write an antiquotation for type patterns. Its code is |
892 we can write an antiquotation for type patterns. Its code is |
893 \<close> |
893 \<close> |
894 |
894 |
979 |
979 |
980 text \<open> |
980 text \<open> |
981 The data can be retrieved with the projection functions defined above. |
981 The data can be retrieved with the projection functions defined above. |
982 |
982 |
983 @{ML_matchresult_fake [display, gray] |
983 @{ML_matchresult_fake [display, gray] |
984 "project_int (nth foo_list 0); |
984 \<open>project_int (nth foo_list 0); |
985 project_bool (nth foo_list 1)" |
985 project_bool (nth foo_list 1)\<close> |
986 "13 |
986 \<open>13 |
987 true"} |
987 true\<close>} |
988 |
988 |
989 Notice that we access the integer as an integer and the boolean as |
989 Notice that we access the integer as an integer and the boolean as |
990 a boolean. If we attempt to access the integer as a boolean, then we get |
990 a boolean. If we attempt to access the integer as a boolean, then we get |
991 a runtime error. |
991 a runtime error. |
992 |
992 |
993 @{ML_matchresult_fake [display, gray] |
993 @{ML_matchresult_fake [display, gray] |
994 "project_bool (nth foo_list 0)" |
994 \<open>project_bool (nth foo_list 0)\<close> |
995 "*** exception Match raised"} |
995 \<open>*** exception Match raised\<close>} |
996 |
996 |
997 This runtime error is the reason why ML is still type-sound despite |
997 This runtime error is the reason why ML is still type-sound despite |
998 containing a universal type. |
998 containing a universal type. |
999 |
999 |
1000 Now, Isabelle heavily uses this mechanism for storing all sorts of |
1000 Now, Isabelle heavily uses this mechanism for storing all sorts of |
1061 The use of the command \isacommand{setup} makes sure the table in the |
1061 The use of the command \isacommand{setup} makes sure the table in the |
1062 \emph{current} theory is updated (this is explained further in |
1062 \emph{current} theory is updated (this is explained further in |
1063 Section~\ref{sec:theories}). The lookup can now be performed as follows. |
1063 Section~\ref{sec:theories}). The lookup can now be performed as follows. |
1064 |
1064 |
1065 @{ML_matchresult_fake [display, gray] |
1065 @{ML_matchresult_fake [display, gray] |
1066 "lookup @{theory} \"conj\"" |
1066 \<open>lookup @{theory} "conj"\<close> |
1067 "SOME \"\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q\""} |
1067 \<open>SOME "\<lbrakk>?P; ?Q\<rbrakk> \<Longrightarrow> ?P \<and> ?Q"\<close>} |
1068 |
1068 |
1069 An important point to note is that these tables (and data in general) |
1069 An important point to note is that these tables (and data in general) |
1070 need to be treated in a purely functional fashion. Although |
1070 need to be treated in a purely functional fashion. Although |
1071 we can update the table as follows |
1071 we can update the table as follows |
1072 \<close> |
1072 \<close> |
1075 |
1075 |
1076 text \<open> |
1076 text \<open> |
1077 and accordingly, @{ML lookup} now produces the introduction rule for @{term "True"} |
1077 and accordingly, @{ML lookup} now produces the introduction rule for @{term "True"} |
1078 |
1078 |
1079 @{ML_matchresult_fake [display, gray] |
1079 @{ML_matchresult_fake [display, gray] |
1080 "lookup @{theory} \"conj\"" |
1080 \<open>lookup @{theory} "conj"\<close> |
1081 "SOME \"True\""} |
1081 \<open>SOME "True"\<close>} |
1082 |
1082 |
1083 there are no references involved. This is one of the most fundamental |
1083 there are no references involved. This is one of the most fundamental |
1084 coding conventions for programming in Isabelle. References |
1084 coding conventions for programming in Isabelle. References |
1085 interfere with the multithreaded execution model of Isabelle and also |
1085 interfere with the multithreaded execution model of Isabelle and also |
1086 defeat its undo-mechanism. To see the latter, consider the |
1086 defeat its undo-mechanism. To see the latter, consider the |
1116 |
1116 |
1117 setup %gray \<open>ref_update 1\<close> |
1117 setup %gray \<open>ref_update 1\<close> |
1118 |
1118 |
1119 text \<open> |
1119 text \<open> |
1120 A lookup in the current theory gives then the expected list |
1120 A lookup in the current theory gives then the expected list |
1121 @{ML "ref [1]" in Unsynchronized}. |
1121 @{ML \<open>ref [1]\<close> in Unsynchronized}. |
1122 |
1122 |
1123 @{ML_matchresult_fake [display,gray] |
1123 @{ML_matchresult_fake [display,gray] |
1124 "WrongRefData.get @{theory}" |
1124 \<open>WrongRefData.get @{theory}\<close> |
1125 "ref [1]"} |
1125 \<open>ref [1]\<close>} |
1126 |
1126 |
1127 So far everything is as expected. But, the trouble starts if we attempt to |
1127 So far everything is as expected. But, the trouble starts if we attempt to |
1128 backtrack to the ``point'' before the \isacommand{setup}-command. There, we |
1128 backtrack to the ``point'' before the \isacommand{setup}-command. There, we |
1129 would expect that the list is empty again. But since it is stored in a |
1129 would expect that the list is empty again. But since it is stored in a |
1130 reference, Isabelle has no control over it. So it is not empty, but still |
1130 reference, Isabelle has no control over it. So it is not empty, but still |
1131 @{ML "ref [1]" in Unsynchronized}. Adding to the trouble, if we execute the |
1131 @{ML \<open>ref [1]\<close> in Unsynchronized}. Adding to the trouble, if we execute the |
1132 \isacommand{setup}-command again, we do not obtain @{ML "ref [1]" in |
1132 \isacommand{setup}-command again, we do not obtain @{ML \<open>ref [1]\<close> in |
1133 Unsynchronized}, but |
1133 Unsynchronized}, but |
1134 |
1134 |
1135 @{ML_matchresult_fake [display,gray] |
1135 @{ML_matchresult_fake [display,gray] |
1136 "WrongRefData.get @{theory}" |
1136 \<open>WrongRefData.get @{theory}\<close> |
1137 "ref [1, 1]"} |
1137 \<open>ref [1, 1]\<close>} |
1138 |
1138 |
1139 Now imagine how often you go backwards and forwards in your proof |
1139 Now imagine how often you go backwards and forwards in your proof |
1140 scripts.\footnote{The same problem can be triggered in the Jedit GUI by |
1140 scripts.\footnote{The same problem can be triggered in the Jedit GUI by |
1141 making the parser to go over and over again over the \isacommand{setup} command.} |
1141 making the parser to go over and over again over the \isacommand{setup} command.} |
1142 By using references in Isabelle code, you are bound to cause all |
1142 By using references in Isabelle code, you are bound to cause all |
1178 text \<open> |
1178 text \<open> |
1179 Next we start with the context generated by the antiquotation |
1179 Next we start with the context generated by the antiquotation |
1180 \<open>@{context}\<close> and update it in various ways. |
1180 \<open>@{context}\<close> and update it in various ways. |
1181 |
1181 |
1182 @{ML_matchresult_fake [display,gray] |
1182 @{ML_matchresult_fake [display,gray] |
1183 "let |
1183 \<open>let |
1184 val ctxt0 = @{context} |
1184 val ctxt0 = @{context} |
1185 val ctxt1 = ctxt0 |> update @{term \"False\"} |
1185 val ctxt1 = ctxt0 |> update @{term "False"} |
1186 |> update @{term \"True \<and> True\"} |
1186 |> update @{term "True \<and> True"} |
1187 val ctxt2 = ctxt0 |> update @{term \"1::nat\"} |
1187 val ctxt2 = ctxt0 |> update @{term "1::nat"} |
1188 val ctxt3 = ctxt2 |> update @{term \"2::nat\"} |
1188 val ctxt3 = ctxt2 |> update @{term "2::nat"} |
1189 in |
1189 in |
1190 print ctxt0; |
1190 print ctxt0; |
1191 print ctxt1; |
1191 print ctxt1; |
1192 print ctxt2; |
1192 print ctxt2; |
1193 print ctxt3 |
1193 print ctxt3 |
1194 end" |
1194 end\<close> |
1195 "Empty! |
1195 \<open>Empty! |
1196 True \<and> True, False |
1196 True \<and> True, False |
1197 1 |
1197 1 |
1198 2, 1"} |
1198 2, 1\<close>} |
1199 |
1199 |
1200 Many functions in Isabelle manage and update data in a similar |
1200 Many functions in Isabelle manage and update data in a similar |
1201 fashion. Consequently, such calculations with contexts occur frequently in |
1201 fashion. Consequently, such calculations with contexts occur frequently in |
1202 Isabelle code, although the ``context flow'' is usually only linear. |
1202 Isabelle code, although the ``context flow'' is usually only linear. |
1203 Note also that the calculation above has no effect on the underlying |
1203 Note also that the calculation above has no effect on the underlying |
1270 text \<open> |
1270 text \<open> |
1271 The rules in the list can be retrieved using the function |
1271 The rules in the list can be retrieved using the function |
1272 @{ML FooRules.get}: |
1272 @{ML FooRules.get}: |
1273 |
1273 |
1274 @{ML_matchresult_fake [display,gray] |
1274 @{ML_matchresult_fake [display,gray] |
1275 "FooRules.get @{context}" |
1275 \<open>FooRules.get @{context}\<close> |
1276 "[\"True\", \"?C\",\"?B\"]"} |
1276 \<open>["True", "?C","?B"]\<close>} |
1277 |
1277 |
1278 Note that this function takes a proof context as argument. This might be |
1278 Note that this function takes a proof context as argument. This might be |
1279 confusing, since the theorem list is stored as theory data. It becomes clear by knowing |
1279 confusing, since the theorem list is stored as theory data. It becomes clear by knowing |
1280 that the proof context contains the information about the current theory and so the function |
1280 that the proof context contains the information about the current theory and so the function |
1281 can access the theorem list in the theory via the context. |
1281 can access the theorem list in the theory via the context. |
1307 text \<open> |
1307 text \<open> |
1308 On the ML-level these values can be retrieved using the |
1308 On the ML-level these values can be retrieved using the |
1309 function @{ML_ind get in Config} from a proof context |
1309 function @{ML_ind get in Config} from a proof context |
1310 |
1310 |
1311 @{ML_matchresult [display,gray] |
1311 @{ML_matchresult [display,gray] |
1312 "Config.get @{context} bval" |
1312 \<open>Config.get @{context} bval\<close> |
1313 "true"} |
1313 \<open>true\<close>} |
1314 |
1314 |
1315 or directly from a theory using the function @{ML_ind get_global in Config} |
1315 or directly from a theory using the function @{ML_ind get_global in Config} |
1316 |
1316 |
1317 @{ML_matchresult [display,gray] |
1317 @{ML_matchresult [display,gray] |
1318 "Config.get_global @{theory} bval" |
1318 \<open>Config.get_global @{theory} bval\<close> |
1319 "true"} |
1319 \<open>true\<close>} |
1320 |
1320 |
1321 It is also possible to manipulate the configuration values |
1321 It is also possible to manipulate the configuration values |
1322 from the ML-level with the functions @{ML_ind put in Config} |
1322 from the ML-level with the functions @{ML_ind put in Config} |
1323 and @{ML_ind put_global in Config}. For example |
1323 and @{ML_ind put_global in Config}. For example |
1324 |
1324 |
1325 @{ML_matchresult [display,gray] |
1325 @{ML_matchresult [display,gray] |
1326 "let |
1326 \<open>let |
1327 val ctxt = @{context} |
1327 val ctxt = @{context} |
1328 val ctxt' = Config.put sval \"foo\" ctxt |
1328 val ctxt' = Config.put sval "foo" ctxt |
1329 val ctxt'' = Config.put sval \"bar\" ctxt' |
1329 val ctxt'' = Config.put sval "bar" ctxt' |
1330 in |
1330 in |
1331 (Config.get ctxt sval, |
1331 (Config.get ctxt sval, |
1332 Config.get ctxt' sval, |
1332 Config.get ctxt' sval, |
1333 Config.get ctxt'' sval) |
1333 Config.get ctxt'' sval) |
1334 end" |
1334 end\<close> |
1335 "(\"some string\", \"foo\", \"bar\")"} |
1335 \<open>("some string", "foo", "bar")\<close>} |
1336 |
1336 |
1337 A concrete example for a configuration value is |
1337 A concrete example for a configuration value is |
1338 @{ML_ind simp_trace in Raw_Simplifier}, which switches on trace information |
1338 @{ML_ind simp_trace in Raw_Simplifier}, which switches on trace information |
1339 in the simplifier. This can be used for example in the following proof |
1339 in the simplifier. This can be used for example in the following proof |
1340 \<close> |
1340 \<close> |