| author | wenzelm | 
| Sat, 05 Jun 2004 13:06:39 +0200 | |
| changeset 14870 | c5cf7c001313 | 
| parent 14869 | 544be18288e6 | 
| child 14881 | e1f501a14159 | 
| permissions | -rw-r--r-- | 
| 14815 | 1 | (* Title: Pure/General/output.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Makarius, Hagia Maria Sion Abbey (Jerusalem) | |
| 4 | License: GPL (GNU GENERAL PUBLIC LICENSE) | |
| 5 | ||
| 6 | Output channels and diagnostics messages. | |
| 7 | *) | |
| 8 | ||
| 9 | signature BASIC_OUTPUT = | |
| 10 | sig | |
| 11 | val print_mode: string list ref | |
| 12 | val std_output: string -> unit | |
| 13 | val std_error: string -> unit | |
| 14 | val writeln_default: string -> unit | |
| 15 | val writeln_fn: (string -> unit) ref | |
| 16 | val priority_fn: (string -> unit) ref | |
| 17 | val tracing_fn: (string -> unit) ref | |
| 18 | val warning_fn: (string -> unit) ref | |
| 19 | val error_fn: (string -> unit) ref | |
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 20 | val panic_fn: (string -> unit) ref | 
| 14815 | 21 | val writeln: string -> unit | 
| 22 | val priority: string -> unit | |
| 23 | val tracing: string -> unit | |
| 24 | val warning: string -> unit | |
| 25 | val error_msg: string -> unit | |
| 26 | val error: string -> 'a | |
| 27 | val sys_error: string -> 'a | |
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 28 | val panic: string -> unit | 
| 14815 | 29 | val assert: bool -> string -> unit | 
| 30 | val deny: bool -> string -> unit | |
| 31 |   val assert_all: ('a -> bool) -> 'a list -> ('a -> string) -> unit
 | |
| 32 |   val overwrite_warn: (''a * 'b) list * (''a * 'b) -> string -> (''a * 'b) list
 | |
| 33 | datatype 'a error = Error of string | OK of 'a | |
| 34 | val get_error: 'a error -> string option | |
| 35 | val get_ok: 'a error -> 'a option | |
| 36 |   val handle_error: ('a -> 'b) -> 'a -> 'b error
 | |
| 37 | exception ERROR_MESSAGE of string | |
| 38 |   val transform_error: ('a -> 'b) -> 'a -> 'b
 | |
| 39 |   val transform_failure: (exn -> exn) -> ('a -> 'b) -> 'a -> 'b
 | |
| 14869 | 40 | val timing: bool ref | 
| 14815 | 41 | val cond_timeit: bool -> (unit -> 'a) -> 'a | 
| 42 | val timeit: (unit -> 'a) -> 'a | |
| 43 |   val timeap: ('a -> 'b) -> 'a -> 'b
 | |
| 44 |   val timeap_msg: string -> ('a -> 'b) -> 'a -> 'b
 | |
| 45 | end; | |
| 46 | ||
| 47 | signature OUTPUT = | |
| 48 | sig | |
| 49 | include BASIC_OUTPUT | |
| 50 | exception MISSING_DEFAULT_OUTPUT | |
| 51 | val output_width: string -> string * real | |
| 52 | val output: string -> string | |
| 53 | val indent: string * int -> string | |
| 54 | val raw: string -> string | |
| 55 | val add_mode: string -> | |
| 56 | (string -> string * real) * (string * int -> string) * (string -> string) -> unit | |
| 57 | end; | |
| 58 | ||
| 59 | structure Output: OUTPUT = | |
| 60 | struct | |
| 61 | ||
| 62 | (** print modes **) | |
| 63 | ||
| 64 | val print_mode = ref ([]: string list); | |
| 65 | ||
| 66 | val modes = ref (Symtab.empty: | |
| 67 | ((string -> string * real) * (string * int -> string) * (string -> string)) | |
| 68 | Symtab.table); | |
| 69 | ||
| 70 | exception MISSING_DEFAULT_OUTPUT; | |
| 71 | ||
| 72 | fun lookup_mode name = Symtab.lookup (! modes, name); | |
| 73 | ||
| 74 | fun get_mode () = | |
| 75 | (case Library.get_first lookup_mode (! print_mode) of Some p => p | |
| 76 | | None => | |
| 77 | (case lookup_mode "" of Some p => p | |
| 78 | | None => raise MISSING_DEFAULT_OUTPUT)); | |
| 79 | ||
| 80 | fun output_width x = #1 (get_mode ()) x; | |
| 81 | val output = #1 o output_width; | |
| 82 | fun indent x = #2 (get_mode ()) x; | |
| 83 | fun raw x = #3 (get_mode ()) x; | |
| 84 | ||
| 85 | ||
| 86 | ||
| 87 | (** output channels **) | |
| 88 | ||
| 89 | (*process channels -- normally NOT used directly!*) | |
| 90 | fun std_output s = (TextIO.output (TextIO.stdOut, s); TextIO.flushOut TextIO.stdOut); | |
| 91 | fun std_error s = (TextIO.output (TextIO.stdErr, s); TextIO.flushOut TextIO.stdErr); | |
| 92 | ||
| 93 | val writeln_default = std_output o suffix "\n"; | |
| 94 | ||
| 95 | (*hooks for Isabelle channels*) | |
| 96 | val writeln_fn = ref writeln_default; | |
| 97 | val priority_fn = ref (fn s => ! writeln_fn s); | |
| 98 | val tracing_fn = ref (fn s => ! writeln_fn s); | |
| 99 | val warning_fn = ref (std_output o suffix "\n" o prefix_lines "### "); | |
| 100 | val error_fn = ref (std_output o suffix "\n" o prefix_lines "*** "); | |
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 101 | val panic_fn = ref (std_output o suffix "\n" o prefix_lines "!!! "); | 
| 14815 | 102 | |
| 103 | fun writeln s = ! writeln_fn (output s); | |
| 104 | fun priority s = ! priority_fn (output s); | |
| 105 | fun tracing s = ! tracing_fn (output s); | |
| 106 | fun warning s = ! warning_fn (output s); | |
| 107 | fun error_msg s = ! error_fn (output s); | |
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 108 | fun panic_msg s = ! panic_fn (output s); | 
| 14815 | 109 | |
| 110 | (* add_mode *) | |
| 111 | ||
| 112 | fun add_mode name m = | |
| 113 | (if is_none (lookup_mode name) then () | |
| 114 |   else warning ("Redeclaration of symbol print mode: " ^ quote name);
 | |
| 115 | modes := Symtab.update ((name, m), ! modes)); | |
| 116 | ||
| 117 | ||
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 118 | (* output error message and abort to top level, or panic & exit *) | 
| 14815 | 119 | |
| 120 | fun error s = (error_msg s; raise ERROR); | |
| 121 | fun sys_error msg = error ("## SYSTEM ERROR ##\n" ^ msg);
 | |
| 14862 
a43f9e2c6332
Add panic function which exits Isabelle immediately.
 aspinall parents: 
14815diff
changeset | 122 | fun panic s = (panic_msg ("## SYSTEM EXIT ##\n" ^ s); exit 1);
 | 
| 14815 | 123 | |
| 124 | fun assert p msg = if p then () else error msg; | |
| 125 | fun deny p msg = if p then error msg else (); | |
| 126 | ||
| 127 | (*Assert pred for every member of l, generating a message if pred fails*) | |
| 128 | fun assert_all pred l msg_fn = | |
| 129 | let fun asl [] = () | |
| 130 | | asl (x::xs) = if pred x then asl xs else error (msg_fn x) | |
| 131 | in asl l end; | |
| 132 | ||
| 133 | fun overwrite_warn (args as (alist, (a, _))) msg = | |
| 134 | (if is_none (assoc (alist, a)) then () else warning msg; | |
| 135 | overwrite args); | |
| 136 | ||
| 137 | ||
| 138 | ||
| 139 | (** handle errors **) | |
| 140 | ||
| 141 | datatype 'a error = | |
| 142 | Error of string | | |
| 143 | OK of 'a; | |
| 144 | ||
| 145 | fun get_error (Error msg) = Some msg | |
| 146 | | get_error _ = None; | |
| 147 | ||
| 148 | fun get_ok (OK x) = Some x | |
| 149 | | get_ok _ = None; | |
| 150 | ||
| 151 | fun handle_error f x = | |
| 152 | let | |
| 153 | val buffer = ref ([]: string list); | |
| 14869 | 154 | fun store_msg s = buffer := ! buffer @ [s]; | 
| 14815 | 155 | fun err_msg () = if not (null (! buffer)) then error_msg (cat_lines (! buffer)) else (); | 
| 156 | in | |
| 14869 | 157 | (case Result (setmp error_fn store_msg f x) handle exn => Exn exn of | 
| 14815 | 158 | Result y => (err_msg (); OK y) | 
| 159 | | Exn ERROR => Error (cat_lines (! buffer)) | |
| 160 | | Exn exn => (err_msg (); raise exn)) | |
| 161 | end; | |
| 162 | ||
| 163 | ||
| 164 | (* transform ERROR into ERROR_MESSAGE *) | |
| 165 | ||
| 166 | exception ERROR_MESSAGE of string; | |
| 167 | ||
| 168 | fun transform_error f x = | |
| 169 | (case handle_error f x of | |
| 170 | OK y => y | |
| 171 | | Error msg => raise ERROR_MESSAGE msg); | |
| 172 | ||
| 173 | ||
| 174 | (* transform any exception, including ERROR *) | |
| 175 | ||
| 176 | fun transform_failure exn f x = | |
| 177 | transform_error f x handle Interrupt => raise Interrupt | e => raise exn e; | |
| 178 | ||
| 179 | ||
| 180 | ||
| 181 | (** timing **) | |
| 182 | ||
| 14869 | 183 | (*global timing mode*) | 
| 184 | val timing = ref false; | |
| 185 | ||
| 14815 | 186 | (*a conditional timing function: applies f to () and, if the flag is true, | 
| 187 | prints its runtime on warning channel*) | |
| 188 | fun cond_timeit flag f = | |
| 189 | if flag then | |
| 190 | let val start = startTiming() | |
| 191 | val result = f () | |
| 192 | in warning (endTiming start); result end | |
| 193 | else f (); | |
| 194 | ||
| 195 | (*unconditional timing function*) | |
| 196 | fun timeit x = cond_timeit true x; | |
| 197 | ||
| 198 | (*timed application function*) | |
| 199 | fun timeap f x = timeit (fn () => f x); | |
| 200 | fun timeap_msg s f x = (warning s; timeap f x); | |
| 201 | ||
| 202 | end; | |
| 203 | ||
| 204 | structure BasicOutput: BASIC_OUTPUT = Output; | |
| 205 | open BasicOutput; |