# HG changeset patch
# User wenzelm
# Date 1284976991 -7200
# Node ID 386576a416ea3561383afe476d36e88f6decbdd7
# Parent 9d75d65a1a7ab0f9e7e31a1941e517d833151813# Parent 16adc476348fef5eb3b2c2ef072a1e2f35b7c236
merged
diff -r 9d75d65a1a7a -r 386576a416ea NEWS
--- a/NEWS Mon Sep 20 11:55:36 2010 +0200
+++ b/NEWS Mon Sep 20 12:03:11 2010 +0200
@@ -244,6 +244,9 @@
*** ML ***
+* Discontinued Output.debug. Minor INCOMPATIBILITY, use plain writeln
+instead (or tracing for high-volume output).
+
* Configuration option show_question_marks only affects regular pretty
printing of types and terms, not raw Term.string_of_vname.
diff -r 9d75d65a1a7a -r 386576a416ea lib/Tools/mkfifo
--- a/lib/Tools/mkfifo Mon Sep 20 11:55:36 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-#
-# Author: Makarius
-#
-# DESCRIPTION: create named pipe
-
-
-PRG="$(basename "$0")"
-
-function usage()
-{
- echo
- echo "Usage: isabelle $PRG"
- echo
- echo " Create a temporary named pipe and return its name."
- echo
- exit 1
-}
-
-function fail()
-{
- echo "$1" >&2
- exit 2
-}
-
-
-## main
-
-[ "$#" != 0 ] && usage
-
-#FIXME potential race condition wrt. future processes with same pid
-FIFO="/tmp/isabelle-fifo$$"
-
-mkfifo -m 600 "$FIFO" || fail "Failed to create fifo: $FIFO"
-echo "$FIFO"
diff -r 9d75d65a1a7a -r 386576a416ea lib/Tools/rmfifo
--- a/lib/Tools/rmfifo Mon Sep 20 11:55:36 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-#
-# Author: Makarius
-#
-# DESCRIPTION: remove named pipe
-
-
-PRG="$(basename "$0")"
-
-function usage()
-{
- echo
- echo "Usage: isabelle $PRG NAME"
- echo
- echo " Remove an unused named pipe, after producing dummy output"
- echo " to unblock the reader (blocks if no reader present)."
- echo
- exit 1
-}
-
-
-## main
-
-[ "$#" != 1 ] && usage
-FIFO="$1"; shift
-
-if [ -p "$FIFO" ]; then
- echo -n "" >"$FIFO" && rm -f "$FIFO"
-fi
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/General/antiquote.ML
--- a/src/Pure/General/antiquote.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/General/antiquote.ML Mon Sep 20 12:03:11 2010 +0200
@@ -36,7 +36,7 @@
(* report *)
-val report_antiq = Position.report Markup.antiq;
+fun report_antiq pos = Position.report pos Markup.antiq;
fun report report_text (Text x) = report_text x
| report _ (Antiq (_, (pos, _))) = report_antiq pos
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/General/markup.scala
--- a/src/Pure/General/markup.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/General/markup.scala Mon Sep 20 12:03:11 2010 +0200
@@ -235,19 +235,15 @@
val INIT = "init"
val STATUS = "status"
+ val REPORT = "report"
val WRITELN = "writeln"
val TRACING = "tracing"
val WARNING = "warning"
val ERROR = "error"
- val DEBUG = "debug"
val SYSTEM = "system"
- val INPUT = "input"
- val STDIN = "stdin"
val STDOUT = "stdout"
- val SIGNAL = "signal"
val EXIT = "exit"
- val REPORT = "report"
val NO_REPORT = "no_report"
val BAD = "bad"
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/General/position.ML
--- a/src/Pure/General/position.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/General/position.ML Mon Sep 20 12:03:11 2010 +0200
@@ -28,9 +28,9 @@
val properties_of: T -> Properties.T
val default_properties: T -> Properties.T -> Properties.T
val markup: T -> Markup.T -> Markup.T
- val reported_text: Markup.T -> T -> string -> string
- val report_text: Markup.T -> T -> string -> unit
- val report: Markup.T -> T -> unit
+ val reported_text: T -> Markup.T -> string -> string
+ val report_text: T -> Markup.T -> string -> unit
+ val report: T -> Markup.T -> unit
val str_of: T -> string
type range = T * T
val no_range: range
@@ -132,12 +132,12 @@
(* reports *)
-fun reported_text m (pos as Pos (count, _)) txt =
+fun reported_text (pos as Pos (count, _)) m txt =
if invalid_count count then ""
else Markup.markup (markup pos m) txt;
-fun report_text markup pos txt = Output.report (reported_text markup pos txt);
-fun report markup pos = report_text markup pos "";
+fun report_text pos markup txt = Output.report (reported_text pos markup txt);
+fun report pos markup = report_text pos markup "";
(* str_of *)
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/attrib.ML
--- a/src/Pure/Isar/attrib.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/attrib.ML Mon Sep 20 12:03:11 2010 +0200
@@ -108,7 +108,7 @@
let val ((name, _), pos) = Args.dest_src src in
(case Symtab.lookup attrs name of
NONE => error ("Unknown attribute: " ^ quote name ^ Position.str_of pos)
- | SOME (att, _) => (Position.report (Markup.attribute name) pos; att src))
+ | SOME (att, _) => (Position.report pos (Markup.attribute name); att src))
end;
in attr end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/isar_cmd.ML
--- a/src/Pure/Isar/isar_cmd.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/isar_cmd.ML Mon Sep 20 12:03:11 2010 +0200
@@ -494,7 +494,7 @@
(* markup commands *)
fun check_text (txt, pos) state =
- (Position.report Markup.doc_source pos;
+ (Position.report pos Markup.doc_source;
ignore (Thy_Output.eval_antiquote (#1 (Keyword.get_lexicons ())) state (txt, pos)));
fun header_markup txt = Toplevel.keep (fn state =>
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/method.ML
--- a/src/Pure/Isar/method.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/method.ML Mon Sep 20 12:03:11 2010 +0200
@@ -358,7 +358,7 @@
let val ((name, _), pos) = Args.dest_src src in
(case Symtab.lookup meths name of
NONE => error ("Unknown proof method: " ^ quote name ^ Position.str_of pos)
- | SOME (mth, _) => (Position.report (Markup.method name) pos; mth src))
+ | SOME (mth, _) => (Position.report pos (Markup.method name); mth src))
end;
in meth end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/proof_context.ML
--- a/src/Pure/Isar/proof_context.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/proof_context.ML Mon Sep 20 12:03:11 2010 +0200
@@ -333,7 +333,7 @@
val (syms, pos) = Syntax.read_token text;
val c = Type.cert_class tsig (Type.intern_class tsig (Symbol_Pos.content syms))
handle TYPE (msg, _, _) => error (msg ^ Position.str_of pos);
- val _ = Context_Position.report ctxt (Markup.tclass c) pos;
+ val _ = Context_Position.report ctxt pos (Markup.tclass c);
in c end;
@@ -467,7 +467,7 @@
val _ =
if strict then ignore (Consts.the_type consts d) handle TYPE (msg, _, _) => err msg
else ();
- val _ = Context_Position.report ctxt (Markup.const d) pos;
+ val _ = Context_Position.report ctxt pos (Markup.const d);
in t end;
in
@@ -478,13 +478,13 @@
val (c, pos) = token_content text;
in
if Syntax.is_tid c then
- (Context_Position.report ctxt Markup.tfree pos;
+ (Context_Position.report ctxt pos Markup.tfree;
TFree (c, default_sort ctxt (c, ~1)))
else
let
val d = Type.intern_type tsig c;
val decl = Type.the_decl tsig d;
- val _ = Context_Position.report ctxt (Markup.tycon d) pos;
+ val _ = Context_Position.report ctxt pos (Markup.tycon d);
fun err () = error ("Bad type name: " ^ quote d);
val args =
(case decl of
@@ -509,8 +509,8 @@
in
(case (lookup_skolem ctxt c, Variable.is_const ctxt c) of
(SOME x, false) =>
- (Context_Position.report ctxt (Markup.name x
- (if can Name.dest_skolem x then Markup.skolem else Markup.free)) pos;
+ (Context_Position.report ctxt pos
+ (Markup.name x (if can Name.dest_skolem x then Markup.skolem else Markup.free));
Free (x, infer_type ctxt (x, ty)))
| _ => prep_const_proper ctxt strict (c, pos))
end;
@@ -585,17 +585,17 @@
local
-structure Allow_Dummies = Proof_Data(type T = bool fun init _ = false);
+val dummies = Config.bool (Config.declare "ProofContext.dummies" (K (Config.Bool false)));
fun check_dummies ctxt t =
- if Allow_Dummies.get ctxt then t
+ if Config.get ctxt dummies then t
else Term.no_dummy_patterns t handle TERM _ => error "Illegal dummy pattern(s) in term";
fun prepare_dummies ts = #1 (fold_map Term.replace_dummy_patterns ts 1);
in
-val allow_dummies = Allow_Dummies.put true;
+val allow_dummies = Config.put dummies true;
fun prepare_patterns ctxt =
let val Mode {pattern, ...} = get_mode ctxt in
@@ -735,7 +735,7 @@
fun parse_failed ctxt pos msg kind =
cat_error msg ("Failed to parse " ^ kind ^
- Markup.markup Markup.report (Context_Position.reported_text ctxt Markup.bad pos ""));
+ Markup.markup Markup.report (Context_Position.reported_text ctxt pos Markup.bad ""));
fun parse_sort ctxt text =
let
@@ -979,7 +979,8 @@
if name = "" then [Thm.transfer thy Drule.dummy_thm]
else
(case Facts.lookup (Context.Proof ctxt) local_facts name of
- SOME (_, ths) => (Context_Position.report ctxt (Markup.local_fact name) pos;
+ SOME (_, ths) =>
+ (Context_Position.report ctxt pos (Markup.local_fact name);
map (Thm.transfer thy) (Facts.select thmref ths))
| NONE => PureThy.get_fact (Context.Proof ctxt) thy xthmref);
in pick name thms end;
@@ -1009,7 +1010,7 @@
let
val pos = Binding.pos_of b;
val name = full_name ctxt b;
- val _ = Context_Position.report ctxt (Markup.local_fact_decl name) pos;
+ val _ = Context_Position.report ctxt pos (Markup.local_fact_decl name);
val facts = PureThy.name_thmss false name raw_facts;
fun app (th, attrs) x =
@@ -1188,7 +1189,7 @@
|> fold_map declare_var (map2 (fn x' => fn (_, T, mx) => (x', T, mx)) xs' vars)
|-> (map_syntax o Local_Syntax.add_syntax (theory_of ctxt) o map (pair Local_Syntax.Fixed));
val _ = (vars ~~ xs') |> List.app (fn ((b, _, _), x') =>
- Context_Position.report ctxt (Markup.fixed_decl x') (Binding.pos_of b));
+ Context_Position.report ctxt (Binding.pos_of b) (Markup.fixed_decl x'));
in (xs', ctxt'') end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/runtime.ML
--- a/src/Pure/Isar/runtime.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/runtime.ML Mon Sep 20 12:03:11 2010 +0200
@@ -10,6 +10,7 @@
exception TERMINATE
exception EXCURSION_FAIL of exn * string
exception TOPLEVEL_ERROR
+ val debug: bool Unsynchronized.ref
val exn_context: Proof.context option -> exn -> exn
val exn_messages: (exn -> Position.T) -> exn -> string list
val exn_message: (exn -> Position.T) -> exn -> string
@@ -28,6 +29,8 @@
exception EXCURSION_FAIL of exn * string;
exception TOPLEVEL_ERROR;
+val debug = Unsynchronized.ref false;
+
(* exn_context *)
@@ -52,7 +55,7 @@
| _ => cat_lines (("exception " ^ name ^ " raised" ^ pos ^ ":") :: msgs))
end;
- val detailed = ! Output.debugging;
+ val detailed = ! debug;
fun exn_msgs context exn =
if Exn.is_interrupt exn then []
@@ -94,11 +97,10 @@
| msgs => cat_lines msgs);
-
(** controlled execution **)
fun debugging f x =
- if ! Output.debugging then
+ if ! debug then
Exn.release (exception_trace (fn () =>
Exn.Result (f x) handle
exn as UNDEF => Exn.Exn exn
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Isar/toplevel.ML
--- a/src/Pure/Isar/toplevel.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Isar/toplevel.ML Mon Sep 20 12:03:11 2010 +0200
@@ -215,7 +215,7 @@
(** toplevel transitions **)
val quiet = Unsynchronized.ref false;
-val debug = Output.debugging;
+val debug = Runtime.debug;
val interact = Unsynchronized.ref false;
val timing = Output.timing;
val profiling = Unsynchronized.ref 0;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ML/ml_compiler_polyml-5.3.ML
--- a/src/Pure/ML/ml_compiler_polyml-5.3.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ML/ml_compiler_polyml-5.3.ML Mon Sep 20 12:03:11 2010 +0200
@@ -48,12 +48,12 @@
| _ => Position.report_text);
fun report_decl markup loc decl =
- report_text Markup.ML_ref (offset_position_of loc)
+ report_text (offset_position_of loc) Markup.ML_ref
(Markup.markup (Position.markup (position_of decl) markup) "");
fun report loc (PolyML.PTtype types) =
PolyML.NameSpace.displayTypeExpression (types, depth, space)
|> pretty_ml |> Pretty.from_ML |> Pretty.string_of
- |> report_text Markup.ML_typing (offset_position_of loc)
+ |> report_text (offset_position_of loc) Markup.ML_typing
| report loc (PolyML.PTdeclaredAt decl) = report_decl Markup.ML_def loc decl
| report loc (PolyML.PTopenedAt decl) = report_decl Markup.ML_open loc decl
| report loc (PolyML.PTstructureAt decl) = report_decl Markup.ML_struct loc decl
@@ -124,7 +124,7 @@
Markup.markup Markup.no_report
((if hard then "Error" else "Warning") ^ Position.str_of (position_of loc) ^ ":\n") ^
Pretty.string_of (Pretty.from_ML (pretty_ml msg)) ^
- Position.reported_text Markup.report (offset_position_of loc) "";
+ Position.reported_text (offset_position_of loc) Markup.report "";
in if hard then err txt else warn txt end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ML/ml_context.ML
--- a/src/Pure/ML/ml_context.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ML/ml_context.ML Mon Sep 20 12:03:11 2010 +0200
@@ -118,7 +118,8 @@
let val ((name, _), pos) = Args.dest_src src in
(case Symtab.lookup (! global_parsers) name of
NONE => error ("Unknown ML antiquotation command: " ^ quote name ^ Position.str_of pos)
- | SOME scan => (Context_Position.report ctxt (Markup.ML_antiq name) pos;
+ | SOME scan =>
+ (Context_Position.report ctxt pos (Markup.ML_antiq name);
Args.context_syntax "ML antiquotation" (scan pos) src ctxt))
end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ML/ml_lex.ML
--- a/src/Pure/ML/ml_lex.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ML/ml_lex.ML Mon Sep 20 12:03:11 2010 +0200
@@ -112,7 +112,7 @@
in
-fun report_token (Token ((pos, _), (kind, x))) = Position.report (token_markup kind x) pos;
+fun report_token (Token ((pos, _), (kind, x))) = Position.report pos (token_markup kind x);
end;
@@ -265,7 +265,7 @@
fun read pos txt =
let
- val _ = Position.report Markup.ML_source pos;
+ val _ = Position.report pos Markup.ML_source;
val syms = Symbol_Pos.explode (txt, pos);
val termination =
if null syms then []
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ML/ml_syntax.ML
--- a/src/Pure/ML/ml_syntax.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ML/ml_syntax.ML Mon Sep 20 12:03:11 2010 +0200
@@ -62,6 +62,9 @@
if not (Symbol.is_char s) then s
else if s = "\"" then "\\\""
else if s = "\\" then "\\\\"
+ else if s = "\t" then "\\t"
+ else if s = "\n" then "\\n"
+ else if s = "\r" then "\\r"
else
let val c = ord s in
if c < 32 then "\\^" ^ chr (c + ord "@")
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/PIDE/isar_document.scala
--- a/src/Pure/PIDE/isar_document.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/PIDE/isar_document.scala Mon Sep 20 12:03:11 2010 +0200
@@ -70,7 +70,19 @@
}
- /* reported positions */
+ /* specific messages */
+
+ def is_warning(msg: XML.Tree): Boolean =
+ msg match {
+ case XML.Elem(Markup(Markup.WARNING, _), _) => true
+ case _ => false
+ }
+
+ def is_error(msg: XML.Tree): Boolean =
+ msg match {
+ case XML.Elem(Markup(Markup.ERROR, _), _) => true
+ case _ => false
+ }
def is_state(msg: XML.Tree): Boolean =
msg match {
@@ -78,6 +90,9 @@
case _ => false
}
+
+ /* reported positions */
+
private val include_pos = Set(Markup.BINDING, Markup.ENTITY, Markup.REPORT, Markup.POSITION)
def message_positions(command: Command, message: XML.Elem): Set[Text.Range] =
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ProofGeneral/proof_general_emacs.ML
--- a/src/Pure/ProofGeneral/proof_general_emacs.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ProofGeneral/proof_general_emacs.ML Mon Sep 20 12:03:11 2010 +0200
@@ -79,7 +79,6 @@
Output.report_fn := (fn _ => ());
Output.priority_fn := message (special "I") (special "J") "";
Output.tracing_fn := message (special "I" ^ special "V") (special "J") "";
- Output.debug_fn := message (special "K") (special "L") "+++ ";
Output.warning_fn := message (special "K") (special "L") "### ";
Output.error_fn := message (special "M") (special "N") "*** ";
Output.prompt_fn := (fn s => Output.std_output (render s ^ special "S")));
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ProofGeneral/proof_general_pgip.ML
--- a/src/Pure/ProofGeneral/proof_general_pgip.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ProofGeneral/proof_general_pgip.ML Mon Sep 20 12:03:11 2010 +0200
@@ -166,8 +166,7 @@
Output.priority_fn := (fn s => normalmsg Status s);
Output.tracing_fn := (fn s => normalmsg Tracing s);
Output.warning_fn := (fn s => errormsg Message Warning s);
- Output.error_fn := (fn s => errormsg Message Fatal s);
- Output.debug_fn := (fn s => errormsg Message Debug s));
+ Output.error_fn := (fn s => errormsg Message Fatal s));
(* immediate messages *)
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/ROOT.ML
--- a/src/Pure/ROOT.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/ROOT.ML Mon Sep 20 12:03:11 2010 +0200
@@ -96,13 +96,13 @@
use "old_term.ML";
use "General/pretty.ML";
use "context.ML";
+use "config.ML";
use "context_position.ML";
use "sorts.ML";
use "type.ML";
use "logic.ML";
use "Syntax/lexicon.ML";
use "Syntax/simple_syntax.ML";
-use "config.ML";
(* inner syntax *)
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Syntax/lexicon.ML
--- a/src/Pure/Syntax/lexicon.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Syntax/lexicon.ML Mon Sep 20 12:03:11 2010 +0200
@@ -66,7 +66,7 @@
val terminals: string list
val is_terminal: string -> bool
val report_token: Proof.context -> token -> unit
- val report_token_range: Proof.context -> token -> unit
+ val reported_token_range: Proof.context -> token -> string
val matching_tokens: token * token -> bool
val valued_token: token -> bool
val predef_term: string -> token option
@@ -187,12 +187,12 @@
| EOF => Markup.empty;
fun report_token ctxt (Token (kind, _, (pos, _))) =
- Context_Position.report ctxt (token_kind_markup kind) pos;
+ Context_Position.report ctxt pos (token_kind_markup kind);
-fun report_token_range ctxt tok =
+fun reported_token_range ctxt tok =
if is_proper tok
- then Context_Position.report ctxt Markup.token_range (pos_of_token tok)
- else ();
+ then Context_Position.reported_text ctxt (pos_of_token tok) Markup.token_range ""
+ else "";
(* matching_tokens *)
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Syntax/syntax.ML
--- a/src/Pure/Syntax/syntax.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Syntax/syntax.ML Mon Sep 20 12:03:11 2010 +0200
@@ -182,7 +182,7 @@
fun parse_token ctxt markup str =
let
val (syms, pos) = read_token str;
- val _ = Context_Position.report ctxt markup pos;
+ val _ = Context_Position.report ctxt pos markup;
in (syms, pos) end;
local
@@ -361,9 +361,9 @@
(* global pretty printing *)
-structure PrettyGlobal = Proof_Data(type T = bool fun init _ = false);
-val is_pretty_global = PrettyGlobal.get;
-val set_pretty_global = PrettyGlobal.put;
+val pretty_global = Config.bool (Config.declare "Syntax.pretty_global" (K (Config.Bool false)));
+fun is_pretty_global ctxt = Config.get ctxt pretty_global;
+val set_pretty_global = Config.put pretty_global;
val init_pretty_global = set_pretty_global true o ProofContext.init_global;
val pretty_term_global = pretty_term o init_pretty_global;
@@ -710,7 +710,9 @@
val root' = if root <> "prop" andalso is_logtype root then Syn_Ext.logic else root;
val pts = Parser.parse ctxt gram root' (filter Lexicon.is_proper toks)
- handle ERROR msg => (List.app (Lexicon.report_token_range ctxt) toks; error msg);
+ handle ERROR msg =>
+ error (msg ^
+ implode (map (Markup.markup Markup.report o Lexicon.reported_token_range ctxt) toks));
val len = length pts;
val limit = Config.get ctxt ambiguity_limit;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/System/isabelle_process.ML
--- a/src/Pure/System/isabelle_process.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/System/isabelle_process.ML Mon Sep 20 12:03:11 2010 +0200
@@ -3,6 +3,16 @@
Isabelle process wrapper, based on private fifos for maximum
robustness and performance.
+
+Startup phases:
+ . raw Posix process startup with uncontrolled output on stdout/stderr
+ . stdout \002: ML running
+ .. stdin/stdout/stderr freely available (raw ML loop)
+ .. protocol thread initialization
+ ... switch to in_fifo/out_fifo channels (rendezvous via open)
+ ... out_fifo INIT(pid): channels ready
+ ... out_fifo STATUS(keywords)
+ ... out_fifo READY: main loop ready
*)
signature ISABELLE_PROCESS =
@@ -62,9 +72,10 @@
in
-fun standard_message out_stream ch body =
+fun standard_message out_stream with_serial ch body =
message out_stream ch
- ((Markup.serialN, serial_string ()) :: Position.properties_of (Position.thread_data ())) body;
+ ((if with_serial then cons (Markup.serialN, serial_string ()) else I)
+ (Position.properties_of (Position.thread_data ()))) body;
fun init_message out_stream =
message out_stream "A" [(Markup.pidN, process_id ())] (Session.welcome ());
@@ -83,32 +94,24 @@
(OS.Process.sleep (Time.fromMilliseconds 20); try TextIO.flushOut stream; loop ());
in loop end;
-fun rendezvous f fifo =
- let
- val path = File.platform_path (Path.explode fifo);
- val result = f fifo; (*should block until peer is ready*)
- val _ =
- if String.isSuffix "cygwin" ml_platform then () (*Cygwin 1.7: no proper blocking on open*)
- else OS.FileSys.remove path; (*prevent future access*)
- in result end;
-
in
fun setup_channels in_fifo out_fifo =
let
- val in_stream = rendezvous TextIO.openIn in_fifo;
- val out_stream = rendezvous TextIO.openOut out_fifo;
+ (*rendezvous*)
+ val in_stream = TextIO.openIn in_fifo;
+ val out_stream = TextIO.openOut out_fifo;
+
val _ = Simple_Thread.fork false (auto_flush out_stream);
val _ = Simple_Thread.fork false (auto_flush TextIO.stdOut);
val _ = Simple_Thread.fork false (auto_flush TextIO.stdErr);
in
- Output.status_fn := standard_message out_stream "B";
- Output.report_fn := standard_message out_stream "C";
- Output.writeln_fn := standard_message out_stream "D";
- Output.tracing_fn := standard_message out_stream "E";
- Output.warning_fn := standard_message out_stream "F";
- Output.error_fn := standard_message out_stream "G";
- Output.debug_fn := standard_message out_stream "H";
+ Output.status_fn := standard_message out_stream false "B";
+ Output.report_fn := standard_message out_stream false "C";
+ Output.writeln_fn := standard_message out_stream true "D";
+ Output.tracing_fn := standard_message out_stream true "E";
+ Output.warning_fn := standard_message out_stream true "F";
+ Output.error_fn := standard_message out_stream true "G";
Output.priority_fn := ! Output.writeln_fn;
Output.prompt_fn := ignore;
(in_stream, out_stream)
@@ -166,17 +169,21 @@
(* init *)
-fun init in_fifo out_fifo =
+fun init in_fifo out_fifo = ignore (Simple_Thread.fork false (fn () =>
let
+ val _ = OS.Process.sleep (Time.fromMilliseconds 500); (*yield to raw ML toplevel*)
+ val _ = Output.std_output Symbol.STX;
+
+ val _ = quick_and_dirty := true; (* FIXME !? *)
+ val _ = Context.set_thread_data NONE;
val _ = Unsynchronized.change print_mode
(fold (update op =) [isabelle_processN, Keyword.keyword_statusN, Pretty.symbolicN]);
+
val (in_stream, out_stream) = setup_channels in_fifo out_fifo;
val _ = init_message out_stream;
- val _ = quick_and_dirty := true; (* FIXME !? *)
val _ = Keyword.status ();
val _ = Output.status (Markup.markup Markup.ready "");
- val _ = Context.set_thread_data NONE;
- val _ = Simple_Thread.fork false (fn () => (loop in_stream; quit ()));
- in () end;
+ in loop in_stream end));
end;
+
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/System/isabelle_process.scala
--- a/src/Pure/System/isabelle_process.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/System/isabelle_process.scala Mon Sep 20 12:03:11 2010 +0200
@@ -19,30 +19,16 @@
{
/* results */
- object Kind {
- // message markup
- val markup = Map(
+ object Kind
+ {
+ val message_markup = Map(
('A' : Int) -> Markup.INIT,
('B' : Int) -> Markup.STATUS,
('C' : Int) -> Markup.REPORT,
('D' : Int) -> Markup.WRITELN,
('E' : Int) -> Markup.TRACING,
('F' : Int) -> Markup.WARNING,
- ('G' : Int) -> Markup.ERROR,
- ('H' : Int) -> Markup.DEBUG)
- def is_raw(kind: String) =
- kind == Markup.STDOUT
- def is_control(kind: String) =
- kind == Markup.SYSTEM ||
- kind == Markup.SIGNAL ||
- kind == Markup.EXIT
- def is_system(kind: String) =
- kind == Markup.SYSTEM ||
- kind == Markup.INPUT ||
- kind == Markup.STDIN ||
- kind == Markup.SIGNAL ||
- kind == Markup.EXIT ||
- kind == Markup.STATUS
+ ('G' : Int) -> Markup.ERROR)
}
class Result(val message: XML.Elem)
@@ -51,9 +37,10 @@
def properties = message.markup.properties
def body = message.body
- def is_raw = Kind.is_raw(kind)
- def is_control = Kind.is_control(kind)
- def is_system = Kind.is_system(kind)
+ def is_init = kind == Markup.INIT
+ def is_exit = kind == Markup.EXIT
+ def is_stdout = kind == Markup.STDOUT
+ def is_system = kind == Markup.SYSTEM
def is_status = kind == Markup.STATUS
def is_report = kind == Markup.REPORT
def is_ready = is_status && body == List(XML.Elem(Markup.Ready, Nil))
@@ -73,7 +60,7 @@
}
-class Isabelle_Process(system: Isabelle_System, receiver: Actor, args: String*)
+class Isabelle_Process(system: Isabelle_System, timeout: Int, receiver: Actor, args: String*)
{
import Isabelle_Process._
@@ -81,24 +68,107 @@
/* demo constructor */
def this(args: String*) =
- this(new Isabelle_System,
+ this(new Isabelle_System, 10000,
actor { loop { react { case res => Console.println(res) } } }, args: _*)
- /* process information */
+ /* input actors */
+
+ private case class Input_Text(text: String)
+ private case class Input_Chunks(chunks: List[Array[Byte]])
+
+ private case object Close
+ private def close(a: Actor) { if (a != null) a ! Close }
+
+ @volatile private var standard_input: Actor = null
+ @volatile private var command_input: Actor = null
+
+
+ /* process manager */
+
+ private val in_fifo = system.mk_fifo()
+ private val out_fifo = system.mk_fifo()
+ private def rm_fifos() { system.rm_fifo(in_fifo); system.rm_fifo(out_fifo) }
+
+ private val proc =
+ try {
+ val cmdline =
+ List(system.getenv_strict("ISABELLE_PROCESS"), "-W", in_fifo + ":" + out_fifo) ++ args
+ system.execute(true, cmdline: _*)
+ }
+ catch { case e: IOException => rm_fifos(); throw(e) }
+
+ private val stdout_reader =
+ new BufferedReader(new InputStreamReader(proc.getInputStream, Standard_System.charset))
+
+ private val stdin_writer =
+ new BufferedWriter(new OutputStreamWriter(proc.getOutputStream, Standard_System.charset))
+
+ Simple_Thread.actor("process_manager") {
+ val (startup_failed, startup_output) =
+ {
+ val expired = System.currentTimeMillis() + timeout
+ val result = new StringBuilder(100)
- @volatile private var proc: Option[Process] = None
- @volatile private var pid: Option[String] = None
+ var finished = false
+ while (!finished && System.currentTimeMillis() <= expired) {
+ while (!finished && stdout_reader.ready) {
+ val c = stdout_reader.read
+ if (c == 2) finished = true
+ else result += c.toChar
+ }
+ Thread.sleep(10)
+ }
+ (!finished, result.toString)
+ }
+ if (startup_failed) {
+ put_result(Markup.STDOUT, startup_output)
+ put_result(Markup.EXIT, "127")
+ stdin_writer.close
+ Thread.sleep(300) // FIXME !?
+ proc.destroy // FIXME reliable!?
+ }
+ else {
+ put_result(Markup.SYSTEM, startup_output)
+
+ standard_input = stdin_actor()
+ stdout_actor()
+
+ // rendezvous
+ val command_stream = system.fifo_output_stream(in_fifo)
+ val message_stream = system.fifo_input_stream(out_fifo)
+
+ command_input = input_actor(command_stream)
+ message_actor(message_stream)
+
+ val rc = proc.waitFor()
+ Thread.sleep(300) // FIXME !?
+ system_result("Isabelle process terminated")
+ put_result(Markup.EXIT, rc.toString)
+ }
+ rm_fifos()
+ }
/* results */
+ private def system_result(text: String)
+ {
+ receiver ! new Result(XML.Elem(Markup(Markup.SYSTEM, Nil), List(XML.Text(text))))
+ }
+
+
private val xml_cache = new XML.Cache(131071)
private def put_result(kind: String, props: List[(String, String)], body: XML.Body)
{
- if (pid.isEmpty && kind == Markup.INIT)
- pid = props.find(_._1 == Markup.PID).map(_._1)
+ if (pid.isEmpty && kind == Markup.INIT) {
+ rm_fifos()
+ props.find(_._1 == Markup.PID).map(_._1) match {
+ case None => system_result("Bad Isabelle process initialization: missing pid")
+ case p => pid = p
+ }
+ }
val msg = XML.Elem(Markup(kind, props), Isar_Document.clean_message(body))
xml_cache.cache_tree(msg)((message: XML.Tree) =>
@@ -113,34 +183,33 @@
/* signals */
+ @volatile private var pid: Option[String] = None
+
def interrupt()
{
- if (proc.isEmpty) put_result(Markup.SYSTEM, "Cannot interrupt Isabelle: no process")
- else
- pid match {
- case None => put_result(Markup.SYSTEM, "Cannot interrupt Isabelle: unknowd pid")
- case Some(i) =>
- try {
- if (system.execute(true, "kill", "-INT", i).waitFor == 0)
- put_result(Markup.SIGNAL, "INT")
- else
- put_result(Markup.SYSTEM, "Cannot interrupt Isabelle: kill command failed")
- }
- catch { case e: IOException => error("Cannot interrupt Isabelle: " + e.getMessage) }
- }
+ pid match {
+ case None => system_result("Cannot interrupt Isabelle: unknowd pid")
+ case Some(i) =>
+ try {
+ if (system.execute(true, "kill", "-INT", i).waitFor == 0)
+ system_result("Interrupt Isabelle")
+ else
+ system_result("Cannot interrupt Isabelle: kill command failed")
+ }
+ catch { case e: IOException => error("Cannot interrupt Isabelle: " + e.getMessage) }
+ }
}
def kill()
{
- proc match {
- case None => put_result(Markup.SYSTEM, "Cannot kill Isabelle: no process")
- case Some(p) =>
- close()
- Thread.sleep(500) // FIXME !?
- put_result(Markup.SIGNAL, "KILL")
- p.destroy
- proc = None
- pid = None
+ val running =
+ try { proc.exitValue; false }
+ catch { case e: java.lang.IllegalThreadStateException => true }
+ if (running) {
+ close()
+ Thread.sleep(500) // FIXME !?
+ system_result("Kill Isabelle")
+ proc.destroy
}
}
@@ -148,45 +217,40 @@
/** stream actors **/
- case class Input_Text(text: String)
- case class Input_Chunks(chunks: List[Array[Byte]])
- case object Close
-
-
/* raw stdin */
- private def stdin_actor(name: String, stream: OutputStream): Actor =
+ private def stdin_actor(): Actor =
+ {
+ val name = "standard_input"
Simple_Thread.actor(name) {
- val writer = new BufferedWriter(new OutputStreamWriter(stream, Standard_System.charset))
var finished = false
while (!finished) {
try {
//{{{
receive {
case Input_Text(text) =>
- // FIXME echo input?!
- writer.write(text)
- writer.flush
+ stdin_writer.write(text)
+ stdin_writer.flush
case Close =>
- writer.close
+ stdin_writer.close
finished = true
case bad => System.err.println(name + ": ignoring bad message " + bad)
}
//}}}
}
- catch {
- case e: IOException => put_result(Markup.SYSTEM, name + ": " + e.getMessage)
- }
+ catch { case e: IOException => system_result(name + ": " + e.getMessage) }
}
- put_result(Markup.SYSTEM, name + " terminated")
+ system_result(name + " terminated")
}
+ }
/* raw stdout */
- private def stdout_actor(name: String, stream: InputStream): Actor =
+ private def stdout_actor(): Actor =
+ {
+ val name = "standard_output"
Simple_Thread.actor(name) {
- val reader = new BufferedReader(new InputStreamReader(stream, Standard_System.charset))
var result = new StringBuilder(100)
var finished = false
@@ -195,8 +259,8 @@
//{{{
var c = -1
var done = false
- while (!done && (result.length == 0 || reader.ready)) {
- c = reader.read
+ while (!done && (result.length == 0 || stdout_reader.ready)) {
+ c = stdout_reader.read
if (c >= 0) result.append(c.asInstanceOf[Char])
else done = true
}
@@ -205,23 +269,23 @@
result.length = 0
}
else {
- reader.close
+ stdout_reader.close
finished = true
- close()
}
//}}}
}
- catch {
- case e: IOException => put_result(Markup.SYSTEM, name + ": " + e.getMessage)
- }
+ catch { case e: IOException => system_result(name + ": " + e.getMessage) }
}
- put_result(Markup.SYSTEM, name + " terminated")
+ system_result(name + " terminated")
}
+ }
/* command input */
- private def input_actor(name: String, raw_stream: OutputStream): Actor =
+ private def input_actor(raw_stream: OutputStream): Actor =
+ {
+ val name = "command_input"
Simple_Thread.actor(name) {
val stream = new BufferedOutputStream(raw_stream)
var finished = false
@@ -241,19 +305,21 @@
}
//}}}
}
- catch {
- case e: IOException => put_result(Markup.SYSTEM, name + ": " + e.getMessage)
- }
+ catch { case e: IOException => system_result(name + ": " + e.getMessage) }
}
- put_result(Markup.SYSTEM, name + " terminated")
+ system_result(name + " terminated")
}
+ }
/* message output */
- private class Protocol_Error(msg: String) extends Exception(msg)
+ private def message_actor(stream: InputStream): Actor =
+ {
+ class EOF extends Exception
+ class Protocol_Error(msg: String) extends Exception(msg)
- private def message_actor(name: String, stream: InputStream): Actor =
+ val name = "message_output"
Simple_Thread.actor(name) {
val default_buffer = new Array[Byte](65536)
var c = -1
@@ -264,6 +330,7 @@
// chunk size
var n = 0
c = stream.read
+ if (c == -1) throw new EOF
while (48 <= c && c <= 57) {
n = 10 * n + (c - 48)
c = stream.read
@@ -294,71 +361,24 @@
val body = read_chunk()
header match {
case List(XML.Elem(Markup(name, props), Nil))
- if name.size == 1 && Kind.markup.isDefinedAt(name(0)) =>
- put_result(Kind.markup(name(0)), props, body)
+ if name.size == 1 && Kind.message_markup.isDefinedAt(name(0)) =>
+ put_result(Kind.message_markup(name(0)), props, body)
case _ => throw new Protocol_Error("bad header: " + header.toString)
}
}
catch {
- case e: IOException =>
- put_result(Markup.SYSTEM, "Cannot read message:\n" + e.getMessage)
- case e: Protocol_Error =>
- put_result(Markup.SYSTEM, "Malformed message:\n" + e.getMessage)
+ case e: IOException => system_result("Cannot read message:\n" + e.getMessage)
+ case e: Protocol_Error => system_result("Malformed message:\n" + e.getMessage)
+ case _: EOF =>
}
} while (c != -1)
stream.close
- close()
- put_result(Markup.SYSTEM, name + " terminated")
+ system_result(name + " terminated")
}
-
-
-
- /** init **/
-
- /* exec process */
-
- private val in_fifo = system.mk_fifo()
- private val out_fifo = system.mk_fifo()
- private def rm_fifos() = { system.rm_fifo(in_fifo); system.rm_fifo(out_fifo) }
-
- try {
- val cmdline =
- List(system.getenv_strict("ISABELLE_PROCESS"), "-W", in_fifo + ":" + out_fifo) ++ args
- proc = Some(system.execute(true, cmdline: _*))
- }
- catch {
- case e: IOException =>
- rm_fifos()
- error("Failed to execute Isabelle process: " + e.getMessage)
}
- /* I/O actors */
-
- private val standard_input = stdin_actor("standard_input", proc.get.getOutputStream)
- stdout_actor("standard_output", proc.get.getInputStream)
-
- private val command_input = input_actor("command_input", system.fifo_output_stream(in_fifo))
- message_actor("message_output", system.fifo_input_stream(out_fifo))
-
-
- /* exit process */
-
- Simple_Thread.actor("process_exit") {
- proc match {
- case None =>
- case Some(p) =>
- val rc = p.waitFor()
- Thread.sleep(300) // FIXME property!?
- put_result(Markup.SYSTEM, "process_exit terminated")
- put_result(Markup.EXIT, rc.toString)
- }
- rm_fifos()
- }
-
-
-
/** main methods **/
def input_raw(text: String): Unit = standard_input ! Input_Text(text)
@@ -369,5 +389,5 @@
def input(name: String, args: String*): Unit =
input_bytes(name, args.map(Standard_System.string_bytes): _*)
- def close(): Unit = command_input ! Close
+ def close(): Unit = { close(command_input); close(standard_input) }
}
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/System/isabelle_system.scala
--- a/src/Pure/System/isabelle_system.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/System/isabelle_system.scala Mon Sep 20 12:03:11 2010 +0200
@@ -273,17 +273,28 @@
/* named pipes */
+ private var fifo_count: Long = 0
+ private def next_fifo(): String = synchronized {
+ require(fifo_count < java.lang.Long.MAX_VALUE)
+ fifo_count += 1
+ fifo_count.toString
+ }
+
def mk_fifo(): String =
{
- val (result, rc) = isabelle_tool("mkfifo")
- if (rc == 0) result.trim
+ val i = next_fifo()
+ val script =
+ "FIFO=\"/tmp/isabelle-fifo-${PPID}-$$-" + i + "\"\n" +
+ "mkfifo -m 600 \"$FIFO\" || { echo \"Failed to create fifo: $FIFO\" >&2; exit 2; }\n" +
+ "echo -n \"$FIFO\"\n"
+ val (result, rc) = bash_output(script)
+ if (rc == 0) result
else error(result)
}
def rm_fifo(fifo: String)
{
- val (result, rc) = isabelle_tool("rmfifo", fifo)
- if (rc != 0) error(result)
+ bash_output("rm -f '" + fifo + "'")
}
def fifo_input_stream(fifo: String): InputStream =
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/System/session.scala
--- a/src/Pure/System/session.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/System/session.scala Mon Sep 20 12:03:11 2010 +0200
@@ -200,8 +200,8 @@
case _ => if (!result.is_ready) bad_result(result)
}
}
- else if (result.kind == Markup.EXIT) prover = null
- else if (result.is_raw) raw_output.event(result)
+ else if (result.is_exit) prover = null // FIXME ??
+ else if (result.is_stdout) raw_output.event(result)
else if (!result.is_system) bad_result(result) // FIXME syslog for system messages (!?)
}
}
@@ -216,7 +216,7 @@
while (
receiveWithin(0) {
case result: Isabelle_Process.Result =>
- if (result.is_raw) {
+ if (result.is_stdout) {
for (text <- XML.content(result.message))
buf.append(text)
}
@@ -229,16 +229,14 @@
def prover_startup(timeout: Int): Option[String] =
{
receiveWithin(timeout) {
- case result: Isabelle_Process.Result
- if result.kind == Markup.INIT =>
+ case result: Isabelle_Process.Result if result.is_init =>
while (receive {
case result: Isabelle_Process.Result =>
handle_result(result); !result.is_ready
}) {}
None
- case result: Isabelle_Process.Result
- if result.kind == Markup.EXIT =>
+ case result: Isabelle_Process.Result if result.is_exit =>
Some(startup_error())
case TIMEOUT => // FIXME clarify
@@ -247,7 +245,7 @@
}
- /* main loop */
+ /* main loop */ // FIXME proper shutdown
var finished = false
while (!finished) {
@@ -272,7 +270,7 @@
case Started(timeout, args) =>
if (prover == null) {
- prover = new Isabelle_Process(system, self, args:_*) with Isar_Document
+ prover = new Isabelle_Process(system, timeout, self, args:_*) with Isar_Document
val origin = sender
val opt_err = prover_startup(timeout)
if (opt_err.isDefined) prover = null
@@ -282,9 +280,9 @@
case Stop => // FIXME synchronous!?
if (prover != null) {
+ global_state.change(_ => Document.State.init)
prover.kill
prover = null
- finished = true
}
case TIMEOUT => // FIXME clarify
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/System/standard_system.scala
--- a/src/Pure/System/standard_system.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/System/standard_system.scala Mon Sep 20 12:03:11 2010 +0200
@@ -132,9 +132,7 @@
for ((x, y) <- env) proc.environment.put(x, y)
}
proc.redirectErrorStream(redirect)
-
- try { proc.start }
- catch { case e: IOException => error(e.getMessage) }
+ proc.start
}
def process_output(proc: Process): (String, Int) =
@@ -152,8 +150,8 @@
(output, rc)
}
- def raw_exec(cwd: File, env: Map[String, String], redirect: Boolean, args: String*):
- (String, Int) = process_output(raw_execute(cwd, env, redirect, args: _*))
+ def raw_exec(cwd: File, env: Map[String, String], redirect: Boolean, args: String*)
+ : (String, Int) = process_output(raw_execute(cwd, env, redirect, args: _*))
}
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Thy/thy_output.ML
--- a/src/Pure/Thy/thy_output.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Thy/thy_output.ML Mon Sep 20 12:03:11 2010 +0200
@@ -103,7 +103,7 @@
(case Symtab.lookup (! global_commands) name of
NONE => error ("Unknown document antiquotation: " ^ quote name ^ Position.str_of pos)
| SOME f =>
- (Position.report (Markup.doc_antiq name) pos;
+ (Position.report pos (Markup.doc_antiq name);
(fn state => fn ctxt => f src state ctxt handle ERROR msg =>
cat_error msg ("The error(s) above occurred in document antiquotation: " ^
quote name ^ Position.str_of pos))))
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/Thy/thy_syntax.ML
--- a/src/Pure/Thy/thy_syntax.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/Thy/thy_syntax.ML Mon Sep 20 12:03:11 2010 +0200
@@ -84,7 +84,7 @@
Markup.enclose (token_markup tok) (Output.output (Token.unparse tok));
fun report_token tok =
- Position.report (token_markup tok) (Token.position_of tok);
+ Position.report (Token.position_of tok) (token_markup tok);
end;
@@ -152,7 +152,7 @@
Markup.enclose (kind_markup (span_kind span)) (implode (map present_token (span_content span)));
fun report_span span =
- Position.report (kind_markup (span_kind span)) (Position.encode_range (span_range span));
+ Position.report (Position.encode_range (span_range span)) (kind_markup (span_kind span));
end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/context_position.ML
--- a/src/Pure/context_position.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/context_position.ML Mon Sep 20 12:03:11 2010 +0200
@@ -10,30 +10,25 @@
val set_visible: bool -> Proof.context -> Proof.context
val restore_visible: Proof.context -> Proof.context -> Proof.context
val if_visible: Proof.context -> ('a -> unit) -> 'a -> unit
- val reported_text: Proof.context -> Markup.T -> Position.T -> string -> string
- val report_text: Proof.context -> Markup.T -> Position.T -> string -> unit
- val report: Proof.context -> Markup.T -> Position.T -> unit
+ val reported_text: Proof.context -> Position.T -> Markup.T -> string -> string
+ val report_text: Proof.context -> Position.T -> Markup.T -> string -> unit
+ val report: Proof.context -> Position.T -> Markup.T -> unit
end;
structure Context_Position: CONTEXT_POSITION =
struct
-structure Data = Proof_Data
-(
- type T = bool;
- fun init _ = true;
-);
-
-val is_visible = Data.get;
-val set_visible = Data.put;
+val visible = Config.bool (Config.declare "Context_Position.visible" (K (Config.Bool true)));
+fun is_visible ctxt = Config.get ctxt visible;
+val set_visible = Config.put visible;
val restore_visible = set_visible o is_visible;
fun if_visible ctxt f x = if is_visible ctxt then f x else ();
-fun reported_text ctxt markup pos txt =
- if is_visible ctxt then Position.reported_text markup pos txt else "";
+fun reported_text ctxt pos markup txt =
+ if is_visible ctxt then Position.reported_text pos markup txt else "";
-fun report_text ctxt markup pos txt = Output.report (reported_text ctxt markup pos txt);
-fun report ctxt markup pos = report_text ctxt markup pos "";
+fun report_text ctxt pos markup txt = Output.report (reported_text ctxt pos markup txt);
+fun report ctxt pos markup = report_text ctxt pos markup "";
end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/pure_thy.ML
--- a/src/Pure/pure_thy.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/pure_thy.ML Mon Sep 20 12:03:11 2010 +0200
@@ -93,7 +93,7 @@
(case res of
NONE => error ("Unknown fact " ^ quote name ^ Position.str_of pos)
| SOME (static, ths) =>
- (Position.report ((if static then Markup.fact else Markup.dynamic_fact) name) pos;
+ (Position.report pos ((if static then Markup.fact else Markup.dynamic_fact) name);
Facts.select xthmref (map (Thm.transfer thy) ths)))
end;
@@ -188,7 +188,7 @@
let
val pos = Binding.pos_of b;
val name = Sign.full_name thy b;
- val _ = Position.report (Markup.fact_decl name) pos;
+ val _ = Position.report pos (Markup.fact_decl name);
fun app (x, (ths, atts)) = Library.foldl_map (Thm.theory_attributes atts) (x, ths);
val (thms, thy') = thy |> enter_thms
diff -r 9d75d65a1a7a -r 386576a416ea src/Pure/sign.ML
--- a/src/Pure/sign.ML Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Pure/sign.ML Mon Sep 20 12:03:11 2010 +0200
@@ -426,7 +426,7 @@
let
val pos = Binding.pos_of b;
val ([const as Const (c, _)], thy') = gen_add_consts (K I) [(b, T, mx)] thy;
- val _ = Position.report (Markup.const_decl c) pos;
+ val _ = Position.report pos (Markup.const_decl c);
in (const, thy') end;
end;
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/dist-template/etc/isabelle-jedit.css
--- a/src/Tools/jEdit/dist-template/etc/isabelle-jedit.css Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/dist-template/etc/isabelle-jedit.css Mon Sep 20 12:03:11 2010 +0200
@@ -6,7 +6,6 @@
.tracing { background-color: #F0F8FF; }
.warning { background-color: #EEE8AA; }
.error { background-color: #FFC1C1; }
-.debug { background-color: #FFE4E1; }
.report { display: none; }
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/dist-template/properties/jedit.props
--- a/src/Tools/jEdit/dist-template/properties/jedit.props Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/dist-template/properties/jedit.props Mon Sep 20 12:03:11 2010 +0200
@@ -177,12 +177,12 @@
end.shortcut=
fallbackEncodings=UTF-8 ISO-8859-15 US-ASCII
firstTime=false
-foldPainter=Circle
home.shortcut=
insert-newline-indent.shortcut=
insert-newline.shortcut=ENTER
isabelle-output.dock-position=bottom
isabelle-raw-output.dock-position=bottom
+isabelle-session.dock-position=bottom
isabelle.activate.shortcut=CS+ENTER
line-end.shortcut=END
line-home.shortcut=HOME
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/plugin/Isabelle.props
--- a/src/Tools/jEdit/plugin/Isabelle.props Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/plugin/Isabelle.props Mon Sep 20 12:03:11 2010 +0200
@@ -1,6 +1,6 @@
## Isabelle plugin properties
##
-##:encoding=ISO-8859-1:
+##:encoding=ISO-8859-1:wrap=soft:maxLineLen=100:
#identification
plugin.isabelle.jedit.Plugin.name=Isabelle
@@ -35,13 +35,15 @@
#menu actions
plugin.isabelle.jedit.Plugin.menu.label=Isabelle
-plugin.isabelle.jedit.Plugin.menu=isabelle.activate isabelle.show-output isabelle.show-raw-output isabelle.show-protocol
+plugin.isabelle.jedit.Plugin.menu=isabelle.activate isabelle.session-panel isabelle.show-output isabelle.show-raw-output isabelle.show-protocol
isabelle.activate.label=Activate current buffer
+isabelle.session-panel.label=Prover session panel
isabelle.show-output.label=Show Output
isabelle.show-raw-output.label=Show Raw Output
isabelle.show-protocol.label=Show Protocol
#dockables
+isabelle-session.title=Session
isabelle-output.title=Output
isabelle-raw-output.title=Raw Output
isabelle-protocol.title=Protocol
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/plugin/actions.xml
--- a/src/Tools/jEdit/plugin/actions.xml Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/plugin/actions.xml Mon Sep 20 12:03:11 2010 +0200
@@ -10,6 +10,11 @@
return isabelle.jedit.Isabelle.is_active(view);
+
+
+ wm.addDockableWindow("isabelle-session");
+
+
wm.addDockableWindow("isabelle-output");
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/plugin/dockables.xml
--- a/src/Tools/jEdit/plugin/dockables.xml Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/plugin/dockables.xml Mon Sep 20 12:03:11 2010 +0200
@@ -2,6 +2,9 @@
+
+ new isabelle.jedit.Session_Dockable(view, position);
+
new isabelle.jedit.Output_Dockable(view, position);
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/isabelle_markup.scala
--- a/src/Tools/jEdit/src/jedit/isabelle_markup.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/src/jedit/isabelle_markup.scala Mon Sep 20 12:03:11 2010 +0200
@@ -54,10 +54,13 @@
if (snapshot.is_outdated) None
else
Isar_Document.command_status(state.status) match {
- case Isar_Document.Forked(i) if i > 0 => Some(unfinished_color)
+ case Isar_Document.Forked(i) => if (i > 0) Some(unfinished_color) else None
case Isar_Document.Unprocessed => Some(unfinished_color)
case Isar_Document.Failed => Some(error_color)
- case _ => None
+ case Isar_Document.Finished =>
+ if (state.results.exists(r => Isar_Document.is_error(r._2))) Some(error_color)
+ else if (state.results.exists(r => Isar_Document.is_warning(r._2))) Some(warning_color)
+ else None
}
}
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/isabelle_options.scala
--- a/src/Tools/jEdit/src/jedit/isabelle_options.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/src/jedit/isabelle_options.scala Mon Sep 20 12:03:11 2010 +0200
@@ -7,36 +7,21 @@
package isabelle.jedit
-import javax.swing.{JComboBox, JSpinner}
+import javax.swing.JSpinner
import org.gjt.sp.jedit.AbstractOptionPane
class Isabelle_Options extends AbstractOptionPane("isabelle")
{
- private val logic_name = new JComboBox()
+ private val logic_selector = Isabelle.logic_selector(Isabelle.Property("logic"))
private val relative_font_size = new JSpinner()
private val tooltip_font_size = new JSpinner()
private val tooltip_dismiss_delay = new JSpinner()
- private class List_Item(val name: String, val descr: String) {
- def this(name: String) = this(name, name)
- override def toString = descr
- }
-
override def _init()
{
- val logic = Isabelle.Property("logic")
- addComponent(Isabelle.Property("logic.title"), {
- logic_name.addItem(new List_Item("", "default (" + Isabelle.default_logic() + ")"))
- for (name <- Isabelle.system.find_logics()) {
- val item = new List_Item(name)
- logic_name.addItem(item)
- if (name == logic)
- logic_name.setSelectedItem(item)
- }
- logic_name
- })
+ addComponent(Isabelle.Property("logic.title"), logic_selector.peer)
addComponent(Isabelle.Property("relative-font-size.title"), {
relative_font_size.setValue(Isabelle.Int_Property("relative-font-size", 100))
@@ -57,7 +42,7 @@
override def _save()
{
Isabelle.Property("logic") =
- logic_name.getSelectedItem.asInstanceOf[List_Item].name
+ logic_selector.selection.item.name
Isabelle.Int_Property("relative-font-size") =
relative_font_size.getValue().asInstanceOf[Int]
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/output_dockable.scala
--- a/src/Tools/jEdit/src/jedit/output_dockable.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/src/jedit/output_dockable.scala Mon Sep 20 12:03:11 2010 +0200
@@ -26,13 +26,12 @@
val html_panel =
new HTML_Panel(Isabelle.system, Isabelle.font_family(), scala.math.round(Isabelle.font_size()))
- add(html_panel, BorderLayout.CENTER)
+ set_content(html_panel)
/* component state -- owned by Swing thread */
private var zoom_factor = 100
- private var show_debug = false
private var show_tracing = false
private var follow_caret = true
private var current_command: Option[Command] = None
@@ -68,8 +67,7 @@
val snapshot = doc_view.model.snapshot()
val filtered_results =
snapshot.state(cmd).results.iterator.map(_._2) filter {
- case XML.Elem(Markup(Markup.TRACING, _), _) => show_tracing
- case XML.Elem(Markup(Markup.DEBUG, _), _) => show_debug
+ case XML.Elem(Markup(Markup.TRACING, _), _) => show_tracing // FIXME not scalable
case _ => true
}
html_panel.render(filtered_results.toList)
@@ -122,13 +120,6 @@
private val zoom = new Library.Zoom_Box(factor => { zoom_factor = factor; handle_resize() })
zoom.tooltip = "Zoom factor for basic font size"
- private val debug = new CheckBox("Debug") {
- reactions += { case ButtonClicked(_) => show_debug = this.selected; handle_update() }
- }
- debug.selected = show_debug
- debug.tooltip =
- "Indicate output of debug messages
(also needs to be enabled on the prover side)"
-
private val tracing = new CheckBox("Tracing") {
reactions += { case ButtonClicked(_) => show_tracing = this.selected; handle_update() }
}
@@ -146,7 +137,7 @@
}
update.tooltip = "Update display according to the command at cursor position"
- val controls = new FlowPanel(FlowPanel.Alignment.Right)(zoom, debug, tracing, auto_update, update)
+ val controls = new FlowPanel(FlowPanel.Alignment.Right)(zoom, tracing, auto_update, update)
add(controls.peer, BorderLayout.NORTH)
handle_update()
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/plugin.scala
--- a/src/Tools/jEdit/src/jedit/plugin.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/src/jedit/plugin.scala Mon Sep 20 12:03:11 2010 +0200
@@ -11,9 +11,9 @@
import java.io.{FileInputStream, IOException}
import java.awt.Font
-import javax.swing.JTextArea
import scala.collection.mutable
+import scala.swing.ComboBox
import org.gjt.sp.jedit.{jEdit, GUIUtilities, EBMessage, EBPlugin,
Buffer, EditPane, ServiceManager, View}
@@ -120,27 +120,6 @@
}
- /* settings */
-
- def default_logic(): String =
- {
- val logic = system.getenv("JEDIT_LOGIC")
- if (logic != "") logic
- else system.getenv_strict("ISABELLE_LOGIC")
- }
-
- def isabelle_args(): List[String] =
- {
- val modes = system.getenv("JEDIT_PRINT_MODE").split(",").toList.map("-m" + _)
- val logic = {
- val logic = Property("logic")
- if (logic != null && logic != "") logic
- else default_logic()
- }
- modes ++ List(logic)
- }
-
-
/* main jEdit components */
def jedit_buffers(): Iterator[Buffer] = jEdit.getBuffers().iterator
@@ -170,6 +149,12 @@
private def wm(view: View): DockableWindowManager = view.getDockableWindowManager
+ def docked_session(view: View): Option[Session_Dockable] =
+ wm(view).getDockableWindow("isabelle-session") match {
+ case dockable: Session_Dockable => Some(dockable)
+ case _ => None
+ }
+
def docked_output(view: View): Option[Output_Dockable] =
wm(view).getDockableWindow("isabelle-output") match {
case dockable: Output_Dockable => Some(dockable)
@@ -189,6 +174,45 @@
}
+ /* logic image */
+
+ def default_logic(): String =
+ {
+ val logic = system.getenv("JEDIT_LOGIC")
+ if (logic != "") logic
+ else system.getenv_strict("ISABELLE_LOGIC")
+ }
+
+ class Logic_Entry(val name: String, val description: String)
+ {
+ override def toString = description
+ }
+
+ def logic_selector(logic: String): ComboBox[Logic_Entry] =
+ {
+ val entries =
+ new Logic_Entry("", "default (" + default_logic() + ")") ::
+ system.find_logics().map(name => new Logic_Entry(name, name))
+ val component = new ComboBox(entries)
+ entries.find(_.name == logic) match {
+ case None =>
+ case Some(entry) => component.selection.item = entry
+ }
+ component
+ }
+
+ def isabelle_args(): List[String] =
+ {
+ val modes = system.getenv("JEDIT_PRINT_MODE").split(",").toList.map("-m" + _)
+ val logic = {
+ val logic = Property("logic")
+ if (logic != null && logic != "") logic
+ else default_logic()
+ }
+ modes ++ List(logic)
+ }
+
+
/* manage prover */ // FIXME async!?
private def prover_started(view: View): Boolean =
@@ -196,7 +220,8 @@
val timeout = Int_Property("startup-timeout") max 1000
session.started(timeout, Isabelle.isabelle_args()) match {
case Some(err) =>
- val text = new JTextArea(err); text.setEditable(false)
+ val text = new scala.swing.TextArea(err)
+ text.editable = false
Library.error_dialog(view, null, "Failed to start Isabelle process", text)
false
case None => true
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/raw_output_dockable.scala
--- a/src/Tools/jEdit/src/jedit/raw_output_dockable.scala Mon Sep 20 11:55:36 2010 +0200
+++ b/src/Tools/jEdit/src/jedit/raw_output_dockable.scala Mon Sep 20 12:03:11 2010 +0200
@@ -19,6 +19,7 @@
extends Dockable(view: View, position: String)
{
private val text_area = new TextArea
+ text_area.editable = false
set_content(new ScrollPane(text_area))
diff -r 9d75d65a1a7a -r 386576a416ea src/Tools/jEdit/src/jedit/session_dockable.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/session_dockable.scala Mon Sep 20 12:03:11 2010 +0200
@@ -0,0 +1,37 @@
+/* Title: Tools/jEdit/src/jedit/session_dockable.scala
+ Author: Makarius
+
+Dockable window for prover session management.
+*/
+
+package isabelle.jedit
+
+
+import isabelle._
+
+import scala.actors.Actor._
+import scala.swing.{TextArea, ScrollPane}
+
+import org.gjt.sp.jedit.View
+
+
+class Session_Dockable(view: View, position: String) extends Dockable(view: View, position: String)
+{
+ private val text_area = new TextArea("Isabelle session")
+ text_area.editable = false
+ set_content(new ScrollPane(text_area))
+
+
+ /* main actor */
+
+ private val main_actor = actor {
+ loop {
+ react {
+ case bad => System.err.println("Session_Dockable: ignoring bad message " + bad)
+ }
+ }
+ }
+
+ override def init() { }
+ override def exit() { }
+}