470 text {* |
470 text {* |
471 The combinator @{ML [index] ||>>} plays a central rôle whenever your task is to update a |
471 The combinator @{ML [index] ||>>} plays a central rôle whenever your task is to update a |
472 theory and the update also produces a side-result (for example a theorem). Functions |
472 theory and the update also produces a side-result (for example a theorem). Functions |
473 for such tasks return a pair whose second component is the theory and the fist |
473 for such tasks return a pair whose second component is the theory and the fist |
474 component is the side-result. Using @{ML [index] ||>>}, you can do conveniently the update |
474 component is the side-result. Using @{ML [index] ||>>}, you can do conveniently the update |
475 and also accumulate the side-results. Considder the following simple function. |
475 and also accumulate the side-results. Consider the following simple function. |
476 *} |
476 *} |
477 |
477 |
478 ML %linenosgray{*fun acc_incs x = |
478 ML %linenosgray{*fun acc_incs x = |
479 x |> (fn x => ("", x)) |
479 x |> (fn x => ("", x)) |
480 ||>> (fn x => (x, x + 1)) |
480 ||>> (fn x => (x, x + 1)) |
482 ||>> (fn x => (x, x + 1))*} |
482 ||>> (fn x => (x, x + 1))*} |
483 |
483 |
484 text {* |
484 text {* |
485 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
485 The purpose of Line 2 is to just pair up the argument with a dummy value (since |
486 @{ML [index] "||>>"} operates on pairs). Each of the next three lines just increment |
486 @{ML [index] "||>>"} operates on pairs). Each of the next three lines just increment |
487 the value by one, but also nest the intrermediate results to the left. For example |
487 the value by one, but also nest the intermediate results to the left. For example |
488 |
488 |
489 @{ML_response [display,gray] |
489 @{ML_response [display,gray] |
490 "acc_incs 1" |
490 "acc_incs 1" |
491 "((((\"\", 1), 2), 3), 4)"} |
491 "((((\"\", 1), 2), 3), 4)"} |
492 |
492 |
1590 |
1590 |
1591 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} |
1591 attribute_setup %gray my_thms = {* Attrib.add_del my_add my_del *} |
1592 "maintaining a list of my_thms - rough test only!" |
1592 "maintaining a list of my_thms - rough test only!" |
1593 |
1593 |
1594 text {* |
1594 text {* |
1595 The parser @{ML [index] add_del in Attrib} is a pre-defined parser for |
1595 The parser @{ML [index] add_del in Attrib} is a predefined parser for |
1596 adding and deleting lemmas. Now if you prove the next lemma |
1596 adding and deleting lemmas. Now if you prove the next lemma |
1597 and attach to it the attribute @{text "[my_thms]"} |
1597 and attach to it the attribute @{text "[my_thms]"} |
1598 *} |
1598 *} |
1599 |
1599 |
1600 lemma trueI_2[my_thms]: "True" by simp |
1600 lemma trueI_2[my_thms]: "True" by simp |
1658 ML{*val my_thm_add = MyThmsData.map o Thm.add_thm |
1658 ML{*val my_thm_add = MyThmsData.map o Thm.add_thm |
1659 val my_thm_del = MyThmsData.map o Thm.del_thm*} |
1659 val my_thm_del = MyThmsData.map o Thm.del_thm*} |
1660 |
1660 |
1661 text {* |
1661 text {* |
1662 where @{ML MyThmsData.map} updates the data appropriately. The |
1662 where @{ML MyThmsData.map} updates the data appropriately. The |
1663 corresponding theorem addtributes are |
1663 corresponding theorem attributes are |
1664 *} |
1664 *} |
1665 |
1665 |
1666 ML{*val my_add = Thm.declaration_attribute my_thm_add |
1666 ML{*val my_add = Thm.declaration_attribute my_thm_add |
1667 val my_del = Thm.declaration_attribute my_thm_del *} |
1667 val my_del = Thm.declaration_attribute my_thm_del *} |
1668 |
1668 |
1898 |
1898 |
1899 section {* Pretty-Printing\label{sec:pretty} *} |
1899 section {* Pretty-Printing\label{sec:pretty} *} |
1900 |
1900 |
1901 text {* |
1901 text {* |
1902 So far we printed out only plain strings without any formatting except for |
1902 So far we printed out only plain strings without any formatting except for |
1903 occasional explicit linebreaks using @{text [quotes] "\\n"}. This is |
1903 occasional explicit line breaks using @{text [quotes] "\\n"}. This is |
1904 sufficient for ``quick-and-dirty'' printouts. For something more |
1904 sufficient for ``quick-and-dirty'' printouts. For something more |
1905 sophisticated, Isabelle includes an infrastructure for properly formatting text. |
1905 sophisticated, Isabelle includes an infrastructure for properly formatting text. |
1906 This infrastructure is loosely based on a paper by Oppen~\cite{Oppen80}. Most of |
1906 This infrastructure is loosely based on a paper by Oppen~\cite{Oppen80}. Most of |
1907 its functions do not operate on @{ML_type string}s, but on instances of the |
1907 its functions do not operate on @{ML_type string}s, but on instances of the |
1908 type: |
1908 type: |
1928 ML{*fun pprint prt = writeln (Pretty.string_of prt)*} |
1928 ML{*fun pprint prt = writeln (Pretty.string_of prt)*} |
1929 |
1929 |
1930 text {* |
1930 text {* |
1931 The point of the pretty-printing infrastructure is to give hints about how to |
1931 The point of the pretty-printing infrastructure is to give hints about how to |
1932 layout text and let Isabelle do the actual layout. Let us first explain |
1932 layout text and let Isabelle do the actual layout. Let us first explain |
1933 how you can insert places where a linebreak can occur. For this assume the |
1933 how you can insert places where a line break can occur. For this assume the |
1934 following function that replicates a string n times: |
1934 following function that replicates a string n times: |
1935 *} |
1935 *} |
1936 |
1936 |
1937 ML{*fun rep n str = implode (replicate n str) *} |
1937 ML{*fun rep n str = implode (replicate n str) *} |
1938 |
1938 |
1941 *} |
1941 *} |
1942 |
1942 |
1943 ML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*} |
1943 ML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*} |
1944 |
1944 |
1945 text {* |
1945 text {* |
1946 We deliberately chosed a large string so that is spans over more than one line. |
1946 We deliberately chose a large string so that is spans over more than one line. |
1947 If we print out the string using the usual ``quick-and-dirty'' method, then |
1947 If we print out the string using the usual ``quick-and-dirty'' method, then |
1948 we obtain the ugly output: |
1948 we obtain the ugly output: |
1949 |
1949 |
1950 @{ML_response_fake [display,gray] |
1950 @{ML_response_fake [display,gray] |
1951 "writeln test_str" |
1951 "writeln test_str" |
1962 ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa |
1962 ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa |
1963 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo |
1963 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo |
1964 oooooooooooooobaaaaaaaaaaaar"} |
1964 oooooooooooooobaaaaaaaaaaaar"} |
1965 |
1965 |
1966 However by using pretty types you have the ability to indicate a possible |
1966 However by using pretty types you have the ability to indicate a possible |
1967 linebreak for example at each space. You can achieve this with the function |
1967 line break for example at each space. You can achieve this with the function |
1968 @{ML [index] breaks in Pretty}, which expects a list of pretty types and inserts a |
1968 @{ML [index] breaks in Pretty}, which expects a list of pretty types and inserts a |
1969 possible linebreak in between every two elements in this list. To print |
1969 possible line break in between every two elements in this list. To print |
1970 this list of pretty types as a single string, we concatenate them |
1970 this list of pretty types as a single string, we concatenate them |
1971 with the function @{ML [index] blk in Pretty} as follows: |
1971 with the function @{ML [index] blk in Pretty} as follows: |
1972 |
1972 |
1973 |
1973 |
1974 @{ML_response_fake [display,gray] |
1974 @{ML_response_fake [display,gray] |
2046 |
2046 |
2047 As can be seen, this function prints out the ``set'' so that starting |
2047 As can be seen, this function prints out the ``set'' so that starting |
2048 from the second, each new line as an indentation of 2. |
2048 from the second, each new line as an indentation of 2. |
2049 |
2049 |
2050 If you print out something that goes beyond the capabilities of the |
2050 If you print out something that goes beyond the capabilities of the |
2051 standard functions, you can do realatively easily the formating |
2051 standard functions, you can do relatively easily the formatting |
2052 yourself. Assume you want to print out a list of items where like in ``English'' |
2052 yourself. Assume you want to print out a list of items where like in ``English'' |
2053 the last two items are separated by @{text [quotes] "and"}. For this you can |
2053 the last two items are separated by @{text [quotes] "and"}. For this you can |
2054 write the function |
2054 write the function |
2055 |
2055 |
2056 *} |
2056 *} |
2067 |
2067 |
2068 text {* |
2068 text {* |
2069 where Line 7 prints the beginning of the list and Line |
2069 where Line 7 prints the beginning of the list and Line |
2070 8 the last item. We have to use @{ML "Pretty.brk 1"} in order |
2070 8 the last item. We have to use @{ML "Pretty.brk 1"} in order |
2071 to insert a space (of length 1) before the |
2071 to insert a space (of length 1) before the |
2072 @{text [quotes] "and"}. This space is also a pleace where a linebreak |
2072 @{text [quotes] "and"}. This space is also a place where a line break |
2073 can occur. We do the same ater the @{text [quotes] "and"}. This gives you |
2073 can occur. We do the same after the @{text [quotes] "and"}. This gives you |
2074 for example |
2074 for example |
2075 |
2075 |
2076 @{ML_response_fake [display,gray] |
2076 @{ML_response_fake [display,gray] |
2077 "let |
2077 "let |
2078 val ptrs = map (Pretty.str o string_of_int) (1 upto 22) |
2078 val ptrs = map (Pretty.str o string_of_int) (1 upto 22) |
2102 where a space is. In Lines 4 and 5 we pretty-print the term and its type |
2102 where a space is. In Lines 4 and 5 we pretty-print the term and its type |
2103 using the functions @{ML [index] pretty_term in Syntax} and @{ML [index] |
2103 using the functions @{ML [index] pretty_term in Syntax} and @{ML [index] |
2104 pretty_typ in Syntax}. We also use the function @{ML [index] quote in |
2104 pretty_typ in Syntax}. We also use the function @{ML [index] quote in |
2105 Pretty} in order to enclose the term and type inside quotation marks. In |
2105 Pretty} in order to enclose the term and type inside quotation marks. In |
2106 Line 9 we add a period right after the type without the possibility of a |
2106 Line 9 we add a period right after the type without the possibility of a |
2107 linebreak, because we do not want that a linebreak occurs there. |
2107 line break, because we do not want that a line break occurs there. |
2108 |
2108 |
2109 |
2109 |
2110 Now you can write |
2110 Now you can write |
2111 |
2111 |
2112 @{ML_response_fake [display,gray] |
2112 @{ML_response_fake [display,gray] |
2113 "tell_type @{context} @{term \"min (Suc 0)\"}" |
2113 "tell_type @{context} @{term \"min (Suc 0)\"}" |
2114 "The term \"min (Suc 0)\" has type \"nat \<Rightarrow> nat\"."} |
2114 "The term \"min (Suc 0)\" has type \"nat \<Rightarrow> nat\"."} |
2115 |
2115 |
2116 To see the proper linebreaking, you can try out the function on a bigger term |
2116 To see the proper line breaking, you can try out the function on a bigger term |
2117 and type. For example: |
2117 and type. For example: |
2118 |
2118 |
2119 @{ML_response_fake [display,gray] |
2119 @{ML_response_fake [display,gray] |
2120 "tell_type @{context} @{term \"op = (op = (op = (op = (op = op =))))\"}" |
2120 "tell_type @{context} @{term \"op = (op = (op = (op = (op = op =))))\"}" |
2121 "The term \"op = (op = (op = (op = (op = op =))))\" has type |
2121 "The term \"op = (op = (op = (op = (op = op =))))\" has type |