changed Markup print mode to YXML -- explicitly decode messages before being issued;
authorwenzelm
Thu, 28 Aug 2008 00:33:17 +0200
changeset 28037915b9a777441
parent 28036 a58e4da3d184
child 28038 7a47b1a8790e
changed Markup print mode to YXML -- explicitly decode messages before being issued;
changed Output print mode to plain default -- no escaping;
simplified pgml_sym: produce Pgml.pgmlatom, no special treatment of Ctrl/Raw;
removed unused issue_pgips;
removed obsolete delay_msgs feature -- the script parser never fails, but produces inline error markup;
removed obsolete wrap_pgml;
explicit transformation of messages (pgml_terms and message_content);
remove obsolete split_markup workaround;
misc tuning;
src/Pure/ProofGeneral/proof_general_pgip.ML
     1.1 --- a/src/Pure/ProofGeneral/proof_general_pgip.ML	Thu Aug 28 00:33:15 2008 +0200
     1.2 +++ b/src/Pure/ProofGeneral/proof_general_pgip.ML	Thu Aug 28 00:33:17 2008 +0200
     1.3 @@ -22,7 +22,7 @@
     1.4    val get_currently_open_file : unit -> Path.T option  (* interface focus *)
     1.5  end
     1.6  
     1.7 -structure ProofGeneralPgip : PROOF_GENERAL_PGIP  =
     1.8 +structure ProofGeneralPgip : PROOF_GENERAL_PGIP =
     1.9  struct
    1.10  
    1.11  open Pgip;
    1.12 @@ -34,38 +34,9 @@
    1.13  val pgmlsymbols_flag = ref true;
    1.14  
    1.15  
    1.16 -(* symbol output *)
    1.17 -
    1.18 -local
    1.19 -
    1.20 -fun xsym_output "\\" = "\\\\"
    1.21 -  | xsym_output s = if Symbol.is_raw s then Symbol.decode_raw s else s;
    1.22 -
    1.23 -fun pgml_sym s =
    1.24 -  (case Symbol.decode s of
    1.25 -    Symbol.Char s => XML.text s
    1.26 -  | Symbol.Sym sn =>
    1.27 -    let val ascii = implode (map xsym_output (Symbol.explode s))
    1.28 -    in if !pgmlsymbols_flag then XML.element "sym" [("name", sn)] [XML.text ascii]
    1.29 -       else  ascii end
    1.30 -  | Symbol.Ctrl sn => XML.element "ctrl" [("name", sn)] [XML.text sn] (* FIXME: no such PGML *)
    1.31 -  | Symbol.Raw raw => raw);
    1.32 -
    1.33 -fun pgml_output str =
    1.34 -  let val syms = Symbol.explode str
    1.35 -  in (implode (map pgml_sym syms), Symbol.length syms) end;
    1.36 -
    1.37 -in
    1.38 -
    1.39 -fun setup_proofgeneral_output () =
    1.40 -  Output.add_mode proof_generalN pgml_output Symbol.encode_raw;
    1.41 -
    1.42 -end;
    1.43 -
    1.44 -
    1.45  (* assembling and issuing PGIP packets *)
    1.46  
    1.47 -val pgip_refid  = ref NONE: string option ref;
    1.48 +val pgip_refid = ref NONE: string option ref;
    1.49  val pgip_refseq = ref NONE: int option ref;
    1.50  
    1.51  local
    1.52 @@ -78,12 +49,12 @@
    1.53    fun assemble_pgips pgips =
    1.54      Pgip { tag = SOME pgip_tag,
    1.55             class = pgip_class,
    1.56 -           seq = pgip_serial(),
    1.57 -           id = !pgip_id,
    1.58 -           destid = !pgip_refid,
    1.59 +           seq = pgip_serial (),
    1.60 +           id = ! pgip_id,
    1.61 +           destid = ! pgip_refid,
    1.62             (* destid=refid since Isabelle only communicates back to sender *)
    1.63 -           refid  = !pgip_refid,
    1.64 -           refseq = !pgip_refseq,
    1.65 +           refid = ! pgip_refid,
    1.66 +           refseq = ! pgip_refseq,
    1.67             content = pgips }
    1.68  in
    1.69  
    1.70 @@ -91,108 +62,112 @@
    1.71      pgip_id := getenv "HOSTNAME" ^ "/" ^ getenv "USER" ^ "/" ^
    1.72                 getenv "ISABELLE_PID" ^ "/" ^ Time.toString (Time.now ())
    1.73  
    1.74 -fun matching_pgip_id id = (id = !pgip_id)
    1.75 +fun matching_pgip_id id = (id = ! pgip_id)
    1.76  
    1.77  val output_xml_fn = ref Output.writeln_default
    1.78 -fun output_xml s = (!output_xml_fn) (XML.string_of s);  (* TODO: string buffer *)
    1.79 +fun output_xml s = ! output_xml_fn (XML.string_of s);
    1.80  
    1.81 -val output_pgips =
    1.82 -  XML.string_of o PgipOutput.output o assemble_pgips o map PgipOutput.output;
    1.83 +val output_pgips = XML.string_of o PgipOutput.output o assemble_pgips o map PgipOutput.output;
    1.84  
    1.85 -val output_pgmlterm =
    1.86 -  XML.string_of o Pgml.pgmlterm_to_xml;
    1.87 -
    1.88 -val output_pgmltext =
    1.89 -  XML.string_of o Pgml.pgml_to_xml;
    1.90 +val output_pgmlterm = XML.string_of o Pgml.pgmlterm_to_xml;
    1.91 +val output_pgmltext = XML.string_of o Pgml.pgml_to_xml;
    1.92  
    1.93  
    1.94  fun issue_pgip_rawtext str =
    1.95 -    output_xml (PgipOutput.output (assemble_pgips [XML.Output str]))
    1.96 -
    1.97 -fun issue_pgips pgipops =
    1.98 -    output_xml (PgipOutput.output (assemble_pgips (map PgipOutput.output pgipops)));
    1.99 +  output_xml (PgipOutput.output (assemble_pgips (YXML.parse_body str)));
   1.100  
   1.101  fun issue_pgip pgipop =
   1.102 -    output_xml (PgipOutput.output (assemble_pgips [PgipOutput.output pgipop]));
   1.103 +  output_xml (PgipOutput.output (assemble_pgips [PgipOutput.output pgipop]));
   1.104  
   1.105  end;
   1.106  
   1.107  
   1.108 -fun pgml area terms = Pgml.Pgml { version=NONE,systemid=NONE,
   1.109 -                                  area=SOME area, content=terms }
   1.110  
   1.111  (** messages and notification **)
   1.112  
   1.113 +(* PGML terms *)
   1.114 +
   1.115  local
   1.116 -    val delay_msgs = ref false   (*true: accumulate messages*)
   1.117 -    val delayed_msgs = ref []
   1.118  
   1.119 -    fun queue_or_issue pgip =
   1.120 -        if ! delay_msgs then
   1.121 -            delayed_msgs := pgip :: ! delayed_msgs
   1.122 -        else issue_pgip pgip
   1.123 +fun pgml_sym s =
   1.124 +  if ! pgmlsymbols_flag then
   1.125 +    (case Symbol.decode s of
   1.126 +      Symbol.Sym name => Pgml.Sym {name = name, content = s}
   1.127 +    | _ => Pgml.Str s)
   1.128 +  else Pgml.Str s;
   1.129  
   1.130 -    fun wrap_pgml area s =
   1.131 -        if String.isPrefix "<pgml" s then
   1.132 -            XML.Output s  (* already pgml outermost *)
   1.133 -        else
   1.134 -            Pgml.pgml_to_xml (pgml area [Pgml.Raw (XML.Output s)]) (* mixed *)
   1.135 +val pgml_syms = map pgml_sym o Symbol.explode;
   1.136 +
   1.137 +val token_markups =
   1.138 + [Markup.tclassN, Markup.tfreeN, Markup.tvarN, Markup.freeN,
   1.139 +  Markup.boundN, Markup.varN, Markup.skolemN];
   1.140  
   1.141  in
   1.142 -    fun normalmsg area s =
   1.143 -        let
   1.144 -            val content = wrap_pgml area s
   1.145 -            val pgip = Normalresponse { content=[content] }
   1.146 -        in
   1.147 -            queue_or_issue pgip
   1.148 +
   1.149 +fun pgml_terms (XML.Elem (name, atts, body)) =
   1.150 +      if member (op =) token_markups name then
   1.151 +        let val content = pgml_syms (Buffer.content (fold XML.add_content body Buffer.empty))
   1.152 +        in [Pgml.Atoms {kind = SOME name, content = content}] end
   1.153 +      else
   1.154 +        let val content = maps pgml_terms body in
   1.155 +          if name = Markup.blockN then
   1.156 +            [Pgml.Box {orient = NONE, indent = Properties.get_int atts Markup.indentN, content = content}]
   1.157 +          else if name = Markup.breakN then
   1.158 +            [Pgml.Break {mandatory = NONE, indent = Properties.get_int atts Markup.widthN}]
   1.159 +          else if name = Markup.fbreakN then
   1.160 +            [Pgml.Break {mandatory = SOME true, indent = NONE}]
   1.161 +          else content
   1.162          end
   1.163 +  | pgml_terms (XML.Text text) = map (Pgml.Raw o Pgml.atom_to_xml) (pgml_syms text);
   1.164  
   1.165 -    fun errormsg area fatality s =
   1.166 -        let
   1.167 -            val content = wrap_pgml area s
   1.168 -            val pgip = Errorresponse { fatality=fatality,
   1.169 -                                       location=NONE,
   1.170 -                                       content=[content] }
   1.171 -        in
   1.172 -            queue_or_issue pgip
   1.173 -        end
   1.174 -
   1.175 -    (* Error responses with useful locations *)
   1.176 -    fun error_with_pos area fatality pos s =
   1.177 -        let
   1.178 -              val content = wrap_pgml area s
   1.179 -              val pgip = Errorresponse { fatality=fatality,
   1.180 -                                         location=SOME (PgipIsabelle.location_of_position pos),
   1.181 -                                         content=[content] }
   1.182 -        in
   1.183 -            queue_or_issue pgip
   1.184 -        end
   1.185 -
   1.186 -    fun start_delay_msgs () = (set delay_msgs; delayed_msgs := [])
   1.187 -    fun end_delayed_msgs () = (reset delay_msgs; ! delayed_msgs)
   1.188  end;
   1.189  
   1.190 -(* NB: all of the standard error/message functions now expect already-escaped text.
   1.191 -   FIXME: this may cause us problems now we're generating trees; on the other
   1.192 -   hand the output functions were tuned some time ago, so it ought to be
   1.193 -   enough to use XML.Output always above. *)
   1.194 -(* NB 2: all of standard functions print strings terminated with new lines, but we don't
   1.195 +
   1.196 +(* messages *)
   1.197 +
   1.198 +fun pgml area content =
   1.199 +  Pgml.Pgml {version = NONE, systemid = NONE, area = SOME area, content = content};
   1.200 +
   1.201 +fun message_content default_area s =
   1.202 +  let
   1.203 +    val body = YXML.parse_body s;
   1.204 +    val area =
   1.205 +      (case body of
   1.206 +        [XML.Elem (name, _, _)] =>
   1.207 +          if name = Markup.stateN then PgipTypes.Display else default_area
   1.208 +      | _ => default_area);
   1.209 +  in Pgml.pgml_to_xml (pgml area (maps pgml_terms body)) end;
   1.210 +
   1.211 +
   1.212 +fun normalmsg area s = issue_pgip
   1.213 +  (Normalresponse {content = [message_content area s]});
   1.214 +
   1.215 +fun errormsg area fatality s = issue_pgip
   1.216 +  (Errorresponse {fatality = fatality, location = NONE, content = [message_content area s]});
   1.217 +
   1.218 +(*error responses with useful locations*)
   1.219 +fun error_with_pos area fatality pos s = issue_pgip
   1.220 +  (Errorresponse {
   1.221 +    fatality = fatality,
   1.222 +    location = SOME (PgipIsabelle.location_of_position pos),
   1.223 +    content = [message_content area s]});
   1.224 +
   1.225 +fun panic s = (errormsg Message Panic ("## SYSTEM EXIT ##\n" ^ s); exit 1);
   1.226 +fun nonfatal_error s = errormsg Message Nonfatal s;
   1.227 +fun log_msg s = errormsg Message Log s;
   1.228 +
   1.229 +(* NB: all of standard functions print strings terminated with new lines, but we don't
   1.230     add new lines explicitly in PGIP: they are left implicit.  It means that PGIP messages
   1.231     can't be written without newlines. *)
   1.232 -
   1.233  fun setup_messages () =
   1.234   (Output.writeln_fn := (fn s => normalmsg Message s);
   1.235    Output.status_fn := (fn _ => ());
   1.236    Output.priority_fn := (fn s => normalmsg Status s);
   1.237 -  Output.tracing_fn := (fn s => normalmsg  Tracing s);
   1.238 +  Output.tracing_fn := (fn s => normalmsg Tracing s);
   1.239    Output.warning_fn := (fn s => errormsg Message Warning s);
   1.240    Output.error_fn := (fn s => errormsg Message Fatal s);
   1.241    Output.debug_fn := (fn s => errormsg Message Debug s));
   1.242  
   1.243 -fun panic s = (errormsg Message Panic ("## SYSTEM EXIT ##\n" ^ s); exit 1);
   1.244 -fun nonfatal_error s = errormsg Message Nonfatal s;
   1.245 -fun log_msg s = errormsg Message Log s;
   1.246 -
   1.247  
   1.248  (* immediate messages *)
   1.249  
   1.250 @@ -212,58 +187,6 @@
   1.251                                       completed=completed})
   1.252  
   1.253  
   1.254 -(* common markup *)
   1.255 -
   1.256 -local
   1.257 -
   1.258 -val no_text = chr 0;
   1.259 -
   1.260 -val pgmlterms_no_text= [Pgml.Raw (XML.Output no_text)]
   1.261 -
   1.262 -fun split_markup text =
   1.263 -  (case space_explode no_text text of
   1.264 -    [bg, en] => (bg, en)
   1.265 -  | _ => (error ("Internal error: failed to split XML markup:\n" ^ text); ("", "")));
   1.266 -
   1.267 -
   1.268 -fun block_markup markup =
   1.269 -    let
   1.270 -      val pgml = Pgml.Box { orient = NONE,
   1.271 -                            indent = Markup.get_int markup Markup.indentN,
   1.272 -                            content = pgmlterms_no_text }
   1.273 -    in split_markup (output_pgmlterm pgml) end;
   1.274 -
   1.275 -fun break_markup markup =
   1.276 -    let
   1.277 -      val pgml = Pgml.Break { mandatory = NONE,
   1.278 -                              indent = Markup.get_int markup Markup.widthN }
   1.279 -    in (output_pgmlterm pgml, "") end;
   1.280 -
   1.281 -fun fbreak_markup markup =
   1.282 -    let
   1.283 -      val pgml = Pgml.Break { mandatory = SOME true, indent = NONE }
   1.284 -    in (output_pgmlterm pgml, "") end;
   1.285 -
   1.286 -val state_markup =
   1.287 -    split_markup (output_pgmltext (pgml PgipTypes.Display pgmlterms_no_text))
   1.288 -
   1.289 -val token_markups =
   1.290 - [Markup.tclassN, Markup.tfreeN, Markup.tvarN, Markup.freeN,
   1.291 -  Markup.boundN, Markup.varN, Markup.skolemN];
   1.292 -
   1.293 -in
   1.294 -
   1.295 -val _ = Markup.add_mode proof_generalN (fn (markup as (name, _)) =>
   1.296 -   if name = Markup.blockN then block_markup markup
   1.297 -   else if name = Markup.breakN then break_markup markup
   1.298 -   else if name = Markup.fbreakN then fbreak_markup markup
   1.299 -   else if name = Markup.stateN then state_markup
   1.300 -   else if member (op =) token_markups name then XML.output_markup ("atom", [("kind", name)])
   1.301 -   else ("", ""));
   1.302 -
   1.303 -end;
   1.304 -
   1.305 -
   1.306  (* theory loader actions *)
   1.307  
   1.308  local
   1.309 @@ -698,24 +621,22 @@
   1.310          fun idvalue strings =
   1.311              issue_pgip (Idvalue { thyname=thyname, objtype=objtype, name=name,
   1.312                                    text=[XML.Elem("pgml",[],
   1.313 -                                                 map XML.Output strings)] })
   1.314 +                                                 maps YXML.parse_body strings)] })
   1.315  
   1.316 -        fun string_of_thm th = Output.output
   1.317 -                               (Pretty.string_of
   1.318 +        fun string_of_thm th = Pretty.string_of
   1.319                                     (Display.pretty_thm_aux
   1.320                                          (Syntax.pp_global (Thm.theory_of_thm th))
   1.321                                          false (* quote *)
   1.322                                          false (* show hyps *)
   1.323                                          [] (* asms *)
   1.324 -                                        th))
   1.325 +                                        th)
   1.326  
   1.327          fun strings_of_thm (thy, name) = map string_of_thm (PureThy.get_thms thy name)
   1.328  
   1.329 -        val string_of_thy = Output.output o
   1.330 -                                Pretty.string_of o (ProofDisplay.pretty_full_theory false)
   1.331 +        val string_of_thy = Pretty.string_of o ProofDisplay.pretty_full_theory false
   1.332      in
   1.333          case (thyname, objtype) of
   1.334 -            (_,ObjTheory) => idvalue [string_of_thy (ThyInfo.get_theory name)]
   1.335 +            (_, ObjTheory) => idvalue [string_of_thy (ThyInfo.get_theory name)]
   1.336            | (SOME thy, ObjTheorem) => idvalue (strings_of_thm (ThyInfo.get_theory thy, name))
   1.337            | (NONE, ObjTheorem) => idvalue (strings_of_thm (splitthy name))
   1.338            | (_, ot) => error ("Cannot show objects of type "^(PgipTypes.name_of_objtype ot))
   1.339 @@ -762,16 +683,14 @@
   1.340          val systemdata = #systemdata vs
   1.341          val location = #location vs   (* TODO: extract position *)
   1.342  
   1.343 -        val _ = start_delay_msgs ()   (* gather parsing errs/warns *)
   1.344          val doc = PgipParser.pgip_parser Position.none text
   1.345 -        val errs = end_delayed_msgs ()
   1.346  
   1.347          val sysattrs = PgipTypes.opt_attr "systemdata" systemdata
   1.348          val locattrs = PgipTypes.attrs_of_location location
   1.349       in
   1.350          issue_pgip (Parseresult { attrs= sysattrs@locattrs,
   1.351                                    doc = doc,
   1.352 -                                  errs = map PgipOutput.output errs })
   1.353 +                                  errs = [] })
   1.354      end
   1.355  
   1.356  fun showproofstate _ = isarcmd "pr"
   1.357 @@ -979,7 +898,6 @@
   1.358                                (XML.string_of xml))
   1.359             | SOME inp => (process_input inp)) (* errors later; packet discarded *)
   1.360        | XML.Text t => ignored_text_warning t
   1.361 -      | XML.Output t => ignored_text_warning t
   1.362  and ignored_text_warning t =
   1.363      if size (Symbol.strip_blanks t) > 0 then
   1.364             warning ("Ignored text in PGIP packet: \n" ^ t)
   1.365 @@ -1084,7 +1002,8 @@
   1.366    | init_pgip true =
   1.367        (! initialized orelse
   1.368          (setup_preferences_tweak ();
   1.369 -         setup_proofgeneral_output ();
   1.370 +         Output.add_mode proof_generalN Output.default_output Output.default_escape;
   1.371 +         Markup.add_mode proof_generalN YXML.output_markup;
   1.372           setup_messages ();
   1.373           Output.no_warnings init_outer_syntax ();
   1.374           setup_thy_loader ();
   1.375 @@ -1093,7 +1012,7 @@
   1.376           welcome ();
   1.377           set initialized);
   1.378          sync_thy_loader ();
   1.379 -       change print_mode (cons proof_generalN o remove (op =) proof_generalN);
   1.380 +       change print_mode (update (op =) proof_generalN);
   1.381         pgip_toplevel tty_src);
   1.382  
   1.383