src/Pure/Thy/document_antiquotations.ML
changeset 73765 ebaed09ce06e
parent 73762 14841c6e4d5f
child 73766 e502b40717c7
equal deleted inserted replaced
73764:35d8132633c6 73765:ebaed09ce06e
   303 
   303 
   304 (* ML text *)
   304 (* ML text *)
   305 
   305 
   306 local
   306 local
   307 
   307 
   308 fun ml_text name ml =
   308 fun test_val (ml1, []) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read ");"
   309   Document_Output.antiquotation_verbatim_embedded name (Scan.lift Args.text_input)
   309   | test_val (ml1, ml2) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : " @ ml2 @ ML_Lex.read ");";
   310     (fn ctxt => fn text =>
   310 
   311       let val _ = ML_Context.eval_in (SOME ctxt) ML_Compiler.flags (Input.pos_of text) (ml text)
   311 fun test_op (ml1, ml2) = test_val (ML_Lex.read "op " @ ml1, ml2);
   312       in #1 (Input.source_content text) end);
   312 
   313 
   313 fun test_type (ml1, []) = ML_Lex.read "val _ = NONE : (" @ ml1 @ ML_Lex.read ") option;"
   314 fun ml_enclose bg en source =
   314   | test_type (ml1, ml2) =
   315   ML_Lex.read bg @ ML_Lex.read_source source @ ML_Lex.read en;
   315       ML_Lex.read "val _ = [NONE : (" @ ml1 @ ML_Lex.read ") option, NONE : (" @
   316 
   316       ml2 @ ML_Lex.read ") option];";
   317 val _ = Theory.setup
   317 
   318  (ml_text \<^binding>\<open>ML\<close> (ml_enclose "fn _ => (" ");") #>
   318 fun test_exn (ml1, []) = ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : exn);"
   319   ml_text \<^binding>\<open>ML_op\<close> (ml_enclose "fn _ => (op " ");") #>
   319   | test_exn (ml1, ml2) =
   320   ml_text \<^binding>\<open>ML_type\<close> (ml_enclose "val _ = NONE : (" ") option;") #>
   320       ML_Lex.read "fn _ => (" @ ml1 @ ML_Lex.read " : " @ ml2 @ ML_Lex.read " -> exn);";
   321   ml_text \<^binding>\<open>ML_structure\<close>
   321 
   322     (ml_enclose "functor XXX() = struct structure XX = " " end;") #>
   322 fun test_struct (ml, _) =
   323 
   323   ML_Lex.read "functor XXX() = struct structure XX = " @ ml @ ML_Lex.read " end;";
   324   ml_text \<^binding>\<open>ML_functor\<close>   (* FIXME formal treatment of functor name (!?) *)
   324 
   325     (fn source =>
   325 fun test_functor (Antiquote.Text tok :: _, _) =
   326       ML_Lex.read ("ML_Env.check_functor " ^
   326       ML_Lex.read "ML_Env.check_functor " @
   327         ML_Syntax.print_string (#1 (Input.source_content source)))) #>
   327       ML_Lex.read (ML_Syntax.print_string (ML_Lex.content_of tok))
   328 
   328   | test_functor _ = raise Fail "Bad ML functor specification";
   329   ml_text \<^binding>\<open>ML_text\<close> (K []));
   329 
   330 
   330 val is_name =
   331 in end;
   331   ML_Lex.kind_of #> (fn kind => kind = ML_Lex.Ident orelse kind = ML_Lex.Long_Ident);
       
   332 
       
   333 fun is_ml_identifier ants =
       
   334   forall Antiquote.is_text ants andalso
       
   335     (case filter is_name (map (Antiquote.the_text "") ants) of
       
   336       toks as [_] => Symbol_Pos.is_identifier (Long_Name.base_name (ML_Lex.flatten toks))
       
   337     | _ => false);
       
   338 
       
   339 val parse_ml0 = Args.text_input >> rpair Input.empty;
       
   340 val parse_ml = Args.text_input -- Scan.optional (Args.colon |-- Args.text_input) Input.empty;
       
   341 val parse_type = Args.text_input -- Scan.optional (Args.$$$ "=" |-- Args.text_input) Input.empty;
       
   342 val parse_exn = Args.text_input -- Scan.optional (Args.$$$ "of" |-- Args.text_input) Input.empty;
       
   343 
       
   344 fun antiquotation_ml parse test kind show_kind binding index =
       
   345   Document_Output.antiquotation_raw binding (Scan.lift parse)
       
   346     (fn ctxt => fn (source1, source2) =>
       
   347       let
       
   348         val (ml1, ml2) = apply2 ML_Lex.read_source (source1, source2);
       
   349         val pos = Input.pos_of source1;
       
   350         val _ =
       
   351           ML_Context.eval_in (SOME ctxt) ML_Compiler.flags pos (test (ml1, ml2))
       
   352             handle ERROR msg => error (msg ^ Position.here pos);
       
   353 
       
   354         val (txt1, txt2) = apply2 (#1 o Input.source_content) (source1, source2);
       
   355         val sep = if kind = "type" then "=" else if kind = "exception" then "of" else ":";
       
   356         val txt =
       
   357           if txt2 = "" then txt1
       
   358           else if sep = ":" andalso is_ml_identifier ml1 then txt1 ^ ": " ^ txt2
       
   359           else txt1 ^ " " ^ sep ^ " " ^ txt2;
       
   360 
       
   361         val main_text =
       
   362           Document_Output.verbatim ctxt
       
   363             (if kind = "" orelse not show_kind then txt else kind ^ " " ^ txt);
       
   364 
       
   365         val index_text =
       
   366           index |> Option.map (fn def =>
       
   367             let
       
   368               val ctxt' = Config.put Document_Antiquotation.thy_output_display false ctxt;
       
   369               val kind' = if kind = "" then " (ML)" else " (ML " ^ kind ^ ")";
       
   370               val txt' = Latex.block [Document_Output.verbatim ctxt' txt1, Latex.string kind'];
       
   371               val like = Document_Antiquotation.approx_content ctxt source1;
       
   372             in Latex.index_entry {items = [{text = txt', like = like}], def = def} end);
       
   373       in Latex.block (the_list index_text @ [main_text]) end);
       
   374 
       
   375 fun antiquotation_ml0 test kind =
       
   376   antiquotation_ml parse_ml0 test kind false;
       
   377 
       
   378 fun antiquotation_ml1 parse test kind binding =
       
   379   antiquotation_ml parse test kind true binding (SOME true);
       
   380 
       
   381 in
       
   382 
       
   383 val _ =
       
   384   Theory.setup
       
   385    (Latex.index_variants (antiquotation_ml0 test_val "") \<^binding>\<open>ML\<close> #>
       
   386     Latex.index_variants (antiquotation_ml0 test_op "infix") \<^binding>\<open>ML_infix\<close> #>
       
   387     Latex.index_variants (antiquotation_ml0 test_type "type") \<^binding>\<open>ML_type\<close> #>
       
   388     Latex.index_variants (antiquotation_ml0 test_struct "structure") \<^binding>\<open>ML_structure\<close> #>
       
   389     Latex.index_variants (antiquotation_ml0 test_functor "functor") \<^binding>\<open>ML_functor\<close> #>
       
   390     antiquotation_ml0 (K []) "text" \<^binding>\<open>ML_text\<close> NONE #>
       
   391     antiquotation_ml1 parse_ml test_val "" \<^binding>\<open>define_ML\<close> #>
       
   392     antiquotation_ml1 parse_ml test_op "infix" \<^binding>\<open>define_ML_infix\<close> #>
       
   393     antiquotation_ml1 parse_type test_type "type" \<^binding>\<open>define_ML_type\<close> #>
       
   394     antiquotation_ml1 parse_exn test_exn "exception" \<^binding>\<open>define_ML_exception\<close> #>
       
   395     antiquotation_ml1 parse_ml0 test_struct "structure" \<^binding>\<open>define_ML_structure\<close> #>
       
   396     antiquotation_ml1 parse_ml0 test_functor "functor" \<^binding>\<open>define_ML_functor\<close>);
       
   397 
       
   398 end;
   332 
   399 
   333 
   400 
   334 (* URLs *)
   401 (* URLs *)
   335 
   402 
   336 val escape_url =
   403 val escape_url =