| author | wenzelm | 
| Thu, 21 Aug 2008 17:42:59 +0200 | |
| changeset 27940 | 002718f9c938 | 
| parent 27351 | 6b120fb45278 | 
| child 29606 | fedb8be05f24 | 
| permissions | -rw-r--r-- | 
| 6118 | 1 | (* Title: Pure/General/pretty.ML | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 2 | ID: $Id$ | 
| 8806 | 3 | Author: Lawrence C Paulson, Cambridge University Computer Laboratory | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 4 | Author: Markus Wenzel, TU Munich | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 5 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 6 | Generic pretty printing module. | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 7 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 8 | Loosely based on | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 9 | D. C. Oppen, "Pretty Printing", | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 10 | ACM Transactions on Programming Languages and Systems (1980), 465-483. | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 11 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 12 | The object to be printed is given as a tree with indentation and line | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 13 | breaking information. A "break" inserts a newline if the text until | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 14 | the next break is too long to fit on the current line. After the newline, | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 15 | text is indented to the level of the enclosing block. Normally, if a block | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 16 | is broken then all enclosing blocks will also be broken. Only "inconsistent | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 17 | breaks" are provided. | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 18 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 19 | The stored length of a block is used in breakdist (to treat each inner block as | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 20 | a unit for breaking). | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 21 | *) | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 22 | |
| 23660 
18765718cf62
type output = string indicates raw system output;
 wenzelm parents: 
23659diff
changeset | 23 | type pprint_args = (output -> unit) * (int -> unit) * (int -> unit) * | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 24 | (unit -> unit) * (unit -> unit); | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 25 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 26 | signature PRETTY = | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 27 | sig | 
| 23660 
18765718cf62
type output = string indicates raw system output;
 wenzelm parents: 
23659diff
changeset | 28 | val default_indent: string -> int -> output | 
| 23698 | 29 | val add_mode: string -> (string -> int -> output) -> unit | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 30 | type T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 31 | val str: string -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 32 | val brk: int -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 33 | val fbrk: T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 34 | val breaks: T list -> T list | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 35 | val fbreaks: T list -> T list | 
| 23645 | 36 | val blk: int * T list -> T | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 37 | val block: T list -> T | 
| 23645 | 38 | val strs: string list -> T | 
| 23617 | 39 | val markup: Markup.T -> T list -> T | 
| 26703 | 40 | val mark: Markup.T -> T -> T | 
| 23617 | 41 | val keyword: string -> T | 
| 42 | val command: string -> T | |
| 23638 | 43 | val markup_chunks: Markup.T -> T list -> T | 
| 18802 | 44 | val chunks: T list -> T | 
| 19266 | 45 | val chunks2: T list -> T | 
| 23617 | 46 | val block_enclose: T * T -> T list -> T | 
| 18802 | 47 | val quote: T -> T | 
| 48 | val backquote: T -> T | |
| 49 | val separate: string -> T list -> T list | |
| 50 | val commas: T list -> T list | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 51 | val enclose: string -> string -> T list -> T | 
| 18802 | 52 | val enum: string -> string -> string -> T list -> T | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 53 | val list: string -> string -> T list -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 54 | val str_list: string -> string -> string list -> T | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 55 | val big_list: string -> T list -> T | 
| 9730 | 56 | val indent: int -> T -> T | 
| 23645 | 57 | val unbreakable: T -> T | 
| 58 | val setmargin: int -> unit | |
| 59 |   val setmp_margin: int -> ('a -> 'b) -> 'a -> 'b
 | |
| 60 | val setdepth: int -> unit | |
| 61 | val pprint: T -> pprint_args -> unit | |
| 62 | val symbolicN: string | |
| 16714 | 63 | val output_buffer: T -> Buffer.T | 
| 23660 
18765718cf62
type output = string indicates raw system output;
 wenzelm parents: 
23659diff
changeset | 64 | val output: T -> output | 
| 23645 | 65 | val string_of: T -> string | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 66 | val str_of: T -> string | 
| 23645 | 67 | val writeln: T -> unit | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 68 | type pp | 
| 14972 | 69 | val pp: (term -> T) * (typ -> T) * (sort -> T) * (class list -> T) * (arity -> T) -> pp | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 70 | val term: pp -> term -> T | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 71 | val typ: pp -> typ -> T | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 72 | val sort: pp -> sort -> T | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 73 | val classrel: pp -> class list -> T | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 74 | val arity: pp -> arity -> T | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 75 | val string_of_term: pp -> term -> string | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 76 | val string_of_typ: pp -> typ -> string | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 77 | val string_of_sort: pp -> sort -> string | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 78 | val string_of_classrel: pp -> class list -> string | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 79 | val string_of_arity: pp -> arity -> string | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 80 | end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 81 | |
| 23617 | 82 | structure Pretty: PRETTY = | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 83 | struct | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 84 | |
| 23617 | 85 | (** print mode operations **) | 
| 86 | ||
| 87 | fun default_indent (_: string) = Symbol.spaces; | |
| 88 | ||
| 89 | local | |
| 23698 | 90 |   val default = {indent = default_indent};
 | 
| 23617 | 91 |   val modes = ref (Symtab.make [("", default)]);
 | 
| 92 | in | |
| 23922 
707639e9497d
marked some CRITICAL sections (for multithreading);
 wenzelm parents: 
23787diff
changeset | 93 | fun add_mode name indent = CRITICAL (fn () => | 
| 
707639e9497d
marked some CRITICAL sections (for multithreading);
 wenzelm parents: 
23787diff
changeset | 94 |     change modes (Symtab.update_new (name, {indent = indent})));
 | 
| 23617 | 95 | fun get_mode () = | 
| 24612 | 96 | the_default default (Library.get_first (Symtab.lookup (! modes)) (print_mode_value ())); | 
| 23617 | 97 | end; | 
| 98 | ||
| 99 | fun mode_indent x y = #indent (get_mode ()) x y; | |
| 23645 | 100 | |
| 101 | val output_spaces = Output.output o Symbol.spaces; | |
| 102 | val add_indent = Buffer.add o output_spaces; | |
| 23617 | 103 | |
| 104 | ||
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 105 | |
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 106 | (** printing items: compound phrases, strings, and breaks **) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 107 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 108 | datatype T = | 
| 23617 | 109 | Block of Markup.T * T list * int * int | (*markup, body, indentation, length*) | 
| 23660 
18765718cf62
type output = string indicates raw system output;
 wenzelm parents: 
23659diff
changeset | 110 | String of output * int | (*text, length*) | 
| 23617 | 111 | Break of bool * int; (*mandatory flag, width if not taken*) | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 112 | |
| 23645 | 113 | fun length (Block (_, _, _, len)) = len | 
| 114 | | length (String (_, len)) = len | |
| 115 | | length (Break (_, wd)) = wd; | |
| 116 | ||
| 9730 | 117 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 118 | |
| 23645 | 119 | (** derived operations to create formatting expressions **) | 
| 120 | ||
| 121 | val str = String o Output.output_width; | |
| 122 | ||
| 123 | fun brk wd = Break (false, wd); | |
| 124 | val fbrk = Break (true, 2); | |
| 125 | ||
| 126 | fun breaks prts = Library.separate (brk 1) prts; | |
| 127 | fun fbreaks prts = Library.separate fbrk prts; | |
| 128 | ||
| 129 | fun markup_block m (indent, es) = | |
| 130 | let | |
| 131 | fun sum [] k = k | |
| 132 | | sum (e :: es) k = sum es (length e + k); | |
| 133 | in Block (m, es, indent, sum es 0) end; | |
| 134 | ||
| 135 | val blk = markup_block Markup.none; | |
| 136 | fun block prts = blk (2, prts); | |
| 137 | val strs = block o breaks o map str; | |
| 138 | ||
| 139 | fun markup m prts = markup_block m (0, prts); | |
| 26703 | 140 | fun mark m prt = markup m [prt]; | 
| 141 | fun keyword name = mark (Markup.keyword name) (str name); | |
| 142 | fun command name = mark (Markup.command name) (str name); | |
| 23645 | 143 | |
| 144 | fun markup_chunks m prts = markup m (fbreaks prts); | |
| 145 | val chunks = markup_chunks Markup.none; | |
| 146 | fun chunks2 prts = blk (0, flat (Library.separate [fbrk, fbrk] (map single prts))); | |
| 147 | ||
| 148 | fun block_enclose (p1, p2) ps = chunks [(block o fbreaks) (p1 :: ps), p2]; | |
| 149 | ||
| 150 | fun quote prt = blk (1, [str "\"", prt, str "\""]); | |
| 151 | fun backquote prt = blk (1, [str "`", prt, str "`"]); | |
| 152 | ||
| 153 | fun separate sep prts = | |
| 154 | flat (Library.separate [str sep, brk 1] (map single prts)); | |
| 155 | ||
| 156 | val commas = separate ","; | |
| 157 | ||
| 158 | fun enclose lpar rpar prts = | |
| 159 | block (str lpar :: (prts @ [str rpar])); | |
| 160 | ||
| 161 | fun enum sep lpar rpar prts = enclose lpar rpar (separate sep prts); | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 162 | |
| 23645 | 163 | val list = enum ","; | 
| 164 | fun str_list lpar rpar strs = list lpar rpar (map str strs); | |
| 165 | ||
| 166 | fun big_list name prts = block (fbreaks (str name :: prts)); | |
| 167 | ||
| 168 | fun indent 0 prt = prt | |
| 169 | | indent n prt = blk (0, [str (Symbol.spaces n), prt]); | |
| 170 | ||
| 171 | fun unbreakable (Break (_, wd)) = String (output_spaces wd, wd) | |
| 172 | | unbreakable (Block (m, es, indent, wd)) = Block (m, map unbreakable es, indent, wd) | |
| 173 | | unbreakable (e as String _) = e; | |
| 174 | ||
| 175 | ||
| 176 | ||
| 177 | (** formatting **) | |
| 178 | ||
| 179 | (* margin *) | |
| 180 | ||
| 181 | fun make_margin_info m = | |
| 182 |  {margin = m,                   (*right margin, or page width*)
 | |
| 183 | breakgain = m div 20, (*minimum added space required of a break*) | |
| 184 | emergencypos = m div 2}; (*position too far to right*) | |
| 185 | ||
| 186 | val margin_info = ref (make_margin_info 76); | |
| 187 | fun setmargin m = margin_info := make_margin_info m; | |
| 188 | fun setmp_margin m f = setmp margin_info (make_margin_info m) f; | |
| 189 | ||
| 190 | ||
| 191 | (* depth limitation *) | |
| 192 | ||
| 193 | val depth = ref 0; (*maximum depth; 0 means no limit*) | |
| 194 | fun setdepth dp = (depth := dp); | |
| 195 | ||
| 196 | local | |
| 197 | fun pruning dp (Block (m, bes, indent, wd)) = | |
| 198 | if dp > 0 | |
| 199 | then markup_block m (indent, map (pruning (dp - 1)) bes) | |
| 200 | else str "..." | |
| 201 | | pruning dp e = e | |
| 202 | in | |
| 203 | fun prune e = if ! depth > 0 then pruning (! depth) e else e; | |
| 204 | end; | |
| 205 | ||
| 206 | ||
| 207 | (* formatted output *) | |
| 208 | ||
| 209 | local | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 210 | |
| 17756 | 211 | type text = {tx: Buffer.T, ind: Buffer.T, pos: int, nl: int};
 | 
| 212 | ||
| 213 | val empty: text = | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 214 |  {tx = Buffer.empty,
 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 215 | ind = Buffer.empty, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 216 | pos = 0, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 217 | nl = 0}; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 218 | |
| 17756 | 219 | fun newline {tx, ind, pos, nl} : text =
 | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 220 |  {tx = Buffer.add (Output.output "\n") tx,
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 221 | ind = Buffer.empty, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 222 | pos = 0, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 223 | nl = nl + 1}; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 224 | |
| 23628 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 225 | fun control s {tx, ind, pos: int, nl} : text =
 | 
| 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 226 |  {tx = Buffer.add s tx,
 | 
| 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 227 | ind = ind, | 
| 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 228 | pos = pos, | 
| 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 229 | nl = nl}; | 
| 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 230 | |
| 17756 | 231 | fun string (s, len) {tx, ind, pos: int, nl} : text =
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 232 |  {tx = Buffer.add s tx,
 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 233 | ind = Buffer.add s ind, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 234 | pos = pos + len, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 235 | nl = nl}; | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 236 | |
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 237 | fun blanks wd = string (output_spaces wd, wd); | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 238 | |
| 17756 | 239 | fun indentation (buf, len) {tx, ind, pos, nl} : text =
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 240 | let val s = Buffer.content buf in | 
| 23617 | 241 |    {tx = Buffer.add (mode_indent s len) tx,
 | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 242 | ind = Buffer.add s ind, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 243 | pos = pos + len, | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 244 | nl = nl} | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 245 | end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 246 | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 247 | (*Add the lengths of the expressions until the next Break; if no Break then | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 248 | include "after", to account for text following this block.*) | 
| 23617 | 249 | fun breakdist (Block (_, _, _, len) :: es, after) = len + breakdist (es, after) | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 250 | | breakdist (String (s, len) :: es, after) = len + breakdist (es, after) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 251 | | breakdist (Break _ :: es, after) = 0 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 252 | | breakdist ([], after) = after; | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 253 | |
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 254 | (*Search for the next break (at this or higher levels) and force it to occur.*) | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 255 | fun forcenext [] = [] | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 256 | | forcenext (Break (_, wd) :: es) = Break (true, 0) :: es | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 257 | | forcenext (e :: es) = e :: forcenext es; | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 258 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 259 | (*es is list of expressions to print; | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 260 | blockin is the indentation of the current block; | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 261 | after is the width of the following context until next break.*) | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 262 | fun format ([], _, _) text = text | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 263 |   | format (e :: es, block as (blockind, blockin), after) (text as {ind, pos, nl, ...}) =
 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 264 | (case e of | 
| 23617 | 265 | Block (markup, bes, indent, wd) => | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 266 | let | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 267 |             val {emergencypos, ...} = ! margin_info;
 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 268 | val pos' = pos + indent; | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 269 | val pos'' = pos' mod emergencypos; | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 270 | val block' = | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 271 | if pos' < emergencypos then (ind |> add_indent indent, pos') | 
| 23645 | 272 | else (add_indent pos'' Buffer.empty, pos''); | 
| 23698 | 273 | val (bg, en) = Markup.output markup; | 
| 23617 | 274 | val btext: text = text | 
| 23628 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 275 | |> control bg | 
| 23617 | 276 | |> format (bes, block', breakdist (es, after)) | 
| 23628 
41cdbfb9f77b
markup: emit as control information -- no indent text;
 wenzelm parents: 
23617diff
changeset | 277 | |> control en; | 
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 278 | (*if this block was broken then force the next break*) | 
| 23617 | 279 | val es' = if nl < #nl btext then forcenext es else es; | 
| 280 | in format (es', block, after) btext end | |
| 10952 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 281 | | String str => format (es, block, after) (string str text) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 282 | | Break (force, wd) => | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 283 |           let val {margin, breakgain, ...} = ! margin_info in
 | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 284 | (*no break if text to next break fits on this line | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 285 | or if breaking would add only breakgain to space*) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 286 | format (es, block, after) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 287 | (if not force andalso | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 288 | pos + wd <= Int.max (margin - breakdist (es, after), blockin + breakgain) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 289 | then text |> blanks wd (*just insert wd blanks*) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 290 | else text |> newline |> indentation block) | 
| 
b520e4f1313b
support general indentation (e.g. for non-tt latex output);
 wenzelm parents: 
9730diff
changeset | 291 | end); | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 292 | |
| 23645 | 293 | in | 
| 19266 | 294 | |
| 23645 | 295 | fun formatted e = #tx (format ([prune e], (Buffer.empty, 0), 0) empty); | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 296 | |
| 23645 | 297 | end; | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 298 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 299 | |
| 23645 | 300 | (* special output *) | 
| 18802 | 301 | |
| 23645 | 302 | (*symbolic markup -- no formatting*) | 
| 303 | fun symbolic prt = | |
| 304 | let | |
| 23787 | 305 | fun out (Block (m, [], _, _)) = Buffer.markup m I | 
| 23659 
4b702ac388d6
symbolic output: avoid empty blocks, 1 space for fbreak;
 wenzelm parents: 
23645diff
changeset | 306 | | out (Block (m, prts, indent, _)) = | 
| 23787 | 307 | Buffer.markup m (Buffer.markup (Markup.block indent) (fold out prts)) | 
| 23645 | 308 | | out (String (s, _)) = Buffer.add s | 
| 23787 | 309 | | out (Break (false, wd)) = Buffer.markup (Markup.break wd) (Buffer.add (output_spaces wd)) | 
| 310 | | out (Break (true, _)) = Buffer.markup Markup.fbreak (Buffer.add (output_spaces 1)); | |
| 23645 | 311 | in out prt Buffer.empty end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 312 | |
| 23645 | 313 | (*unformatted output*) | 
| 314 | fun unformatted prt = | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 315 | let | 
| 23787 | 316 | fun fmt (Block (m, prts, _, _)) = Buffer.markup m (fold fmt prts) | 
| 23617 | 317 | | fmt (String (s, _)) = Buffer.add s | 
| 318 | | fmt (Break (false, wd)) = Buffer.add (output_spaces wd) | |
| 319 | | fmt (Break (true, _)) = Buffer.add (output_spaces 1); | |
| 23645 | 320 | in fmt (prune prt) Buffer.empty end; | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 321 | |
| 23645 | 322 | (*ML toplevel pretty printing*) | 
| 27351 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 323 | fun pprint prt (put_str0, begin_blk, put_brk, put_fbrk, end_blk) = | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 324 | let | 
| 27351 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 325 | fun put_str "" = () | 
| 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 326 | | put_str s = put_str0 s; | 
| 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 327 | fun pp (Block (m, prts, ind, _)) = | 
| 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 328 | let val (bg, en) = Markup.output m | 
| 
6b120fb45278
pprint: back to proper output of markup, with workaround for Poly/ML crash;
 wenzelm parents: 
27350diff
changeset | 329 | in put_str bg; begin_blk ind; pp_lst prts; end_blk (); put_str en end | 
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 330 | | pp (String (s, _)) = put_str s | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 331 | | pp (Break (false, wd)) = put_brk wd | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 332 | | pp (Break (true, _)) = put_fbrk () | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 333 | and pp_lst [] = () | 
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 334 | | pp_lst (prt :: prts) = (pp prt; pp_lst prts); | 
| 23645 | 335 | in pp (prune prt) end; | 
| 336 | ||
| 337 | ||
| 338 | (* output interfaces *) | |
| 339 | ||
| 340 | val symbolicN = "pretty_symbolic"; | |
| 341 | ||
| 342 | fun output_buffer prt = | |
| 343 | if print_mode_active symbolicN then symbolic prt | |
| 344 | else formatted prt; | |
| 345 | ||
| 346 | val output = Buffer.content o output_buffer; | |
| 347 | val string_of = Output.escape o output; | |
| 348 | val str_of = Output.escape o Buffer.content o unformatted; | |
| 349 | val writeln = Output.writeln o string_of; | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 350 | |
| 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 351 | |
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 352 | |
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 353 | (** abstract pretty printing context **) | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 354 | |
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 355 | datatype pp = | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 356 | PP of (term -> T) * (typ -> T) * (sort -> T) * (class list -> T) * (arity -> T); | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 357 | |
| 14972 | 358 | val pp = PP; | 
| 14832 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 359 | |
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 360 | fun pp_fun f (PP x) = f x; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 361 | |
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 362 | val term = pp_fun #1; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 363 | val typ = pp_fun #2; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 364 | val sort = pp_fun #3; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 365 | val classrel = pp_fun #4; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 366 | val arity = pp_fun #5; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 367 | |
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 368 | val string_of_term = string_of oo term; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 369 | val string_of_typ = string_of oo typ; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 370 | val string_of_sort = string_of oo sort; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 371 | val string_of_classrel = string_of oo classrel; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 372 | val string_of_arity = string_of oo arity; | 
| 
6589a58f57cb
pp: abstract pretty printing context; string_of/str_of: mark result as raw output; added Pretty.unbreakable;
 wenzelm parents: 
12421diff
changeset | 373 | |
| 6116 
8ba2f25610f7
files scan.ML, source.ML, symbol.ML, pretty.ML moved to Pure/General;
 wenzelm parents: diff
changeset | 374 | end; |