|   1691  |   1691  | 
|   1692 thm foo_def |   1692 thm foo_def | 
|   1693 *) |   1693 *) | 
|   1694 (*>*) |   1694 (*>*) | 
|   1695  |   1695  | 
|   1696 section {* Pretty-Printing (TBD) *} |   1696 section {* Pretty-Printing *} | 
|   1697  |   1697  | 
|   1698 text {* |   1698 text {* | 
|   1699   Isabelle has a pretty sphisticated pretty printing module.  |   1699   Isabelle has a sophisticated infrastructure for pretty-printing text | 
|   1700  |   1700   involving for example long formulae.  This infrastructure is loosely based | 
|   1701   Loosely based on |   1701   on a paper by Oppen~\cite{Oppen80}. Most of its functions do not operate | 
|   1702   D. C. Oppen, "Pretty Printing", |   1702   directly on @{ML_type string}s, but on instances of the type: | 
|   1703   ACM Transactions on Programming Languages and Systems (1980), 465-483. |   1703  | 
|         |   1704   @{ML_type [display, gray] "Pretty.T"} | 
|         |   1705  | 
|         |   1706   The function @{ML "Pretty.str"} transforms a string into such a pretty  | 
|         |   1707   type. For example | 
|         |   1708  | 
|         |   1709   @{ML_response_fake [display,gray] | 
|         |   1710   "Pretty.str \"test\"" "String (\"test\", 4)"} | 
|         |   1711  | 
|         |   1712   where the result indicates that we transformed a string with length 4.  | 
|         |   1713   Once you have a pretty type, you can, for example, control where line breaks  | 
|         |   1714   can occur and with how much indentation a text should be printed. | 
|         |   1715   However, if you want to actually output the formatted text, you have to  | 
|         |   1716   transform the pretty type back into a @{ML_type string}. This can be done  | 
|         |   1717   with the  function @{ML Pretty.string_of}. In what follows we will use  | 
|         |   1718   the following wrapper function for printing a pretty type: | 
|         |   1719 *} | 
|         |   1720  | 
|         |   1721 ML{*fun pprint prt = writeln (Pretty.string_of prt)*} | 
|         |   1722  | 
|         |   1723 text {* | 
|         |   1724   The point of the pretty-printing infrastructure is to aid the layout  | 
|         |   1725   of text. Let us first explain how you can insert places where a | 
|         |   1726   line break can occur. For this assume the following function that  | 
|         |   1727   replicates a string n times: | 
|         |   1728 *} | 
|         |   1729  | 
|         |   1730 ML{*fun rep n str = implode (replicate n str) *} | 
|         |   1731  | 
|         |   1732 text {* | 
|         |   1733   and suppose we want to print out the string: | 
|         |   1734 *} | 
|         |   1735  | 
|         |   1736 ML{*val test_str = rep 8 "fooooooooooooooobaaaaaaaaaaaar "*} | 
|         |   1737  | 
|         |   1738 text {* | 
|         |   1739   If we use for printing the usial ``quick-and-dirty'' method | 
|         |   1740  | 
|         |   1741 @{ML_response_fake [display,gray] | 
|         |   1742 "writeln test_str" | 
|         |   1743 "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar foooooooooo | 
|         |   1744 ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa | 
|         |   1745 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo | 
|         |   1746 oooooooooooooobaaaaaaaaaaaar"} | 
|         |   1747  | 
|         |   1748   we obtain an ugly layout. Similarly if we just use | 
|         |   1749  | 
|         |   1750 @{ML_response_fake [display,gray] | 
|         |   1751 "pprint (Pretty.str test_str)" | 
|         |   1752 "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar foooooooooo | 
|         |   1753 ooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaa | 
|         |   1754 aaaaaaar fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar fo | 
|         |   1755 oooooooooooooobaaaaaaaaaaaar"} | 
|         |   1756  | 
|         |   1757 *} | 
|         |   1758  | 
|         |   1759 text {*  | 
|         |   1760   We obtain better results if we indicate a possible line break at every | 
|         |   1761   spece. You can achieve this with the function @{ML Pretty.breaks}, which | 
|         |   1762   expects a list of pretty types and inserts a possible place for a  | 
|         |   1763   line break in between every two elements in this list. To print this | 
|         |   1764   this list of pretty types we concatenate them with the function @{ML | 
|         |   1765   Pretty.blk} as follows | 
|         |   1766  | 
|         |   1767 @{ML_response_fake [display,gray] | 
|         |   1768 "let | 
|         |   1769   val ptrs = map Pretty.str (space_explode \" \" test_str) | 
|         |   1770 in | 
|         |   1771   pprint (Pretty.blk (0, Pretty.breaks ptrs)) | 
|         |   1772 end" | 
|         |   1773 "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|         |   1774 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|         |   1775 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar | 
|         |   1776 fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"} | 
|         |   1777  | 
|         |   1778   Here the layout of @{ML test_str} is much more pleaseing to the  | 
|         |   1779   eye. The @{ML "0"} in @{ML Pretty.blk} stands for a zero-intendation | 
|         |   1780   of the printed string. If we increase the intentation we obtain | 
|   1704    |   1781    | 
|   1705   Fixme |   1782 @{ML_response_fake [display,gray] | 
|   1706  |   1783 "let | 
|   1707   @{text [display, gray] "Pretty.T"} |   1784   val ptrs = map Pretty.str (space_explode \" \" test_str) | 
|   1708  |   1785 in | 
|   1709   Transforming a string into a pretty |   1786   pprint (Pretty.blk (3, Pretty.breaks ptrs)) | 
|   1710  |   1787 end" | 
|   1711 *} |   1788 "fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|   1712  |   1789    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|   1713 ML {*  |   1790    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar | 
|   1714 fun rep n str = implode (replicate n str) |   1791    fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"} | 
|   1715 *} |   1792  | 
|   1716  |   1793   where starting from the second line the indent is 3. If you want | 
|   1717 ML {* |   1794   that every line starts with the same indent, you can use the | 
|   1718 val test_str = rep 10 "fooooooooooooooobaaaaaaaaaaaar " |   1795   function @{ML Pretty.indent} as follows: | 
|   1719 *} |   1796  | 
|   1720  |   1797 @{ML_response_fake [display,gray] | 
|   1721 ML {*  |   1798 "let | 
|   1722 fun pprint prt = writeln (Pretty.string_of prt) |   1799   val ptrs = map Pretty.str (space_explode \" \" test_str) | 
|   1723 *} |   1800 in | 
|   1724  |   1801   pprint (Pretty.indent 10 (Pretty.blk (0, Pretty.breaks ptrs))) | 
|   1725 ML {*  |   1802 end" | 
|   1726 fun pprint2 prt = priority (Pretty.string_of prt) |   1803 "          fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|   1727 *} |   1804           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar  | 
|   1728  |   1805           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar | 
|   1729  |   1806           fooooooooooooooobaaaaaaaaaaaar fooooooooooooooobaaaaaaaaaaaar"} | 
|   1730 ML {* |   1807  | 
|   1731 pprint (Pretty.str test_str)   |   1808 *}  | 
|   1732 *} |   1809  | 
|   1733  |   1810  | 
|   1734  |   1811 ML{*fun p_strs str = Pretty.breaks (map Pretty.str (space_explode " " str)) *} | 
|   1735  |   1812  | 
|   1736 text {* string of (English) and breaks at each space *} |   1813 ML{*pprint (Pretty.blk (0, Pretty.commas (map (Pretty.str o string_of_int) (1 upto 20))))*} | 
|   1737  |   1814  | 
|   1738 ML {* |   1815 ML{*fun and_list [] = [] | 
|   1739 Pretty.blk   |         | 
|   1740 *} |         | 
|   1741  |         | 
|   1742 text {* integer is indent for the second and later lines*} |         | 
|   1743  |         | 
|   1744 ML {* |         | 
|   1745 fun p_strs str = Pretty.breaks (map Pretty.str (space_explode " " str)) |         | 
|   1746 *} |         | 
|   1747  |         | 
|   1748 ML {* pprint (Pretty.blk (0, p_strs test_str)) *} |         | 
|   1749  |         | 
|   1750 ML {* pprint (Pretty.blk (3, p_strs test_str)) *} |         | 
|   1751  |         | 
|   1752 ML {* Pretty.indent *} |         | 
|   1753  |         | 
|   1754 ML {* pprint (Pretty.indent 10 (Pretty.blk (3, p_strs test_str))) *} |         | 
|   1755  |         | 
|   1756 ML {* string_of_int *} |         | 
|   1757  |         | 
|   1758 ML {* |         | 
|   1759 pprint (Pretty.block (Pretty.commas (map (Pretty.str o string_of_int) (1 upto 20)))) |         | 
|   1760 *} |         | 
|   1761  |         | 
|   1762 ML {* |         | 
|   1763 fun and_list [] = [] |         | 
|   1764   | and_list [x] = [x] |   1816   | and_list [x] = [x] | 
|   1765   | and_list xs =  |   1817   | and_list xs =  | 
|   1766       let val (front,last) = split_last xs |   1818       let  | 
|         |   1819         val (front, last) = split_last xs | 
|   1767       in |   1820       in | 
|   1768         (Pretty.commas front) @ [Pretty.brk 1, Pretty.str "and", Pretty.brk 1, last] |   1821         (Pretty.commas front) @ [Pretty.brk 1, Pretty.str "and", Pretty.brk 1, last] | 
|   1769       end |   1822       end *} | 
|   1770 *} |   1823  | 
|   1771  |   1824 ML{* pprint (Pretty.block (and_list (map (Pretty.str o string_of_int) (1 upto 20)))) *} | 
|   1772 ML {* |   1825  | 
|   1773 pprint (Pretty.block (and_list (map (Pretty.str o string_of_int) (1 upto 20)))) |   1826 ML{* Pretty.enum "l" "r" "sep" *} | 
|   1774 *} |   1827  | 
|   1775  |   1828 text {* chunks = one ptr above the other*} | 
|   1776 ML {*  Pretty.enum "l" "r" "sep" *} |   1829  | 
|   1777  |   1830 ML{* pprint (Pretty.chunks ([(Pretty.str (rep 3 "foo "))] @ [(Pretty.str (rep 4 "bar "))])) *} | 
|   1778 text {* chunks = one ptr above the othere*} |   1831  | 
|   1779  |   1832 ML {* pprint (Pretty.str "foo"); pprint (Pretty.str "bar") *} | 
|   1780 ML {* |         | 
|   1781  pprint (Pretty.chunks ([(Pretty.str (rep 3 "foo "))] @ [(Pretty.str (rep 4 "bar "))])) |         | 
|   1782 *} |         | 
|   1783  |         | 
|   1784 ML {* pprint2 (Pretty.str "foo"); pprint2 (Pretty.str "bar") |         | 
|   1785 *} |         | 
|   1786  |   1833  | 
|   1787  |   1834  | 
|   1788 text {* types, terms and text *} |   1835 text {* types, terms and text *} | 
|   1789  |   1836  | 
|   1790 term "min (Suc 0)" |   1837 ML {*fun tell_type ctxt t =  | 
|   1791  |         | 
|   1792 ML {* fastype_of *} |         | 
|   1793  |         | 
|   1794 ML {* |         | 
|   1795 fun tell_type ctxt t =  |         | 
|   1796   pprint (Pretty.blk (0, (p_strs "The term ")  |   1838   pprint (Pretty.blk (0, (p_strs "The term ")  | 
|   1797                           @ [Pretty.quote (Syntax.pretty_term ctxt t)] |   1839                           @ [Pretty.quote (Syntax.pretty_term ctxt t)] | 
|   1798                           @ p_strs " has type "  |   1840                           @ p_strs " has type "  | 
|   1799                           @ [Pretty.quote (Syntax.pretty_typ ctxt (fastype_of t)), Pretty.str "."])) |   1841                           @ [Pretty.quote (Syntax.pretty_typ ctxt (fastype_of t)), Pretty.str "."]))*} | 
|   1800  |   1842  | 
|   1801 *} |   1843 ML{*tell_type @{context} @{term "min (Suc 0)"} *} | 
|   1802  |         | 
|   1803 ML {* |         | 
|   1804 tell_type @{context} @{term "min (Suc 0)"} |         | 
|   1805 *} |         | 
|   1806  |   1844  | 
|   1807  |   1845  | 
|   1808 ML {* |   1846 ML {* | 
|   1809 tell_type @{context} @{term "(op =) ((op =) ((op =) ((op =) ((op =) (op =)))))"} |   1847 tell_type @{context} @{term "(op =) ((op =) ((op =) ((op =) ((op =) (op =)))))"} | 
|   1810 *} |   1848 *} | 
|   1811  |   1849  | 
|   1812 text {* does not break inside the term or type *} |   1850 text {* does not break inside the term or type *} | 
|   1813  |   1851  | 
|   1814  |         | 
|   1815  |         | 
|   1816  |         | 
|   1817  |         | 
|   1818  |         | 
|   1819  |         | 
|   1820 text {* |   1852 text {* | 
|   1821   @{ML Pretty.big_list}, |   1853   @{ML Pretty.big_list}, | 
|   1822  |   1854  | 
|   1823   equations |   1855   equations | 
|   1824  |   1856  |