ProgTutorial/FirstSteps.thy
changeset 247 afa2d9c6b3b7
parent 245 53112deda119
child 248 11851b20fb78
equal deleted inserted replaced
246:eb81ab6da2a3 247:afa2d9c6b3b7
  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