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 = |