37 a_piece_of_code"} to the ML-compiler (i.e.~the function @{ML |
37 a_piece_of_code"} to the ML-compiler (i.e.~the function @{ML |
38 "ML_Context.eval_source_in"} in Line 7 below). The complete code of the |
38 "ML_Context.eval_source_in"} in Line 7 below). The complete code of the |
39 document antiquotation is as follows: |
39 document antiquotation is as follows: |
40 |
40 |
41 *} |
41 *} |
42 |
42 ML \<open>Input.pos_of\<close> |
43 ML%linenosgray{*fun ml_val code_txt = "val _ = " ^ code_txt |
43 ML%linenosgray{*fun ml_enclose bg en source = |
44 |
44 ML_Lex.read bg @ ML_Lex.read_source false source @ ML_Lex.read en;*} |
45 fun output_ml {context = ctxt, ...} code_txt = |
45 |
|
46 ML%linenosgray{*fun ml_val code_txt = (ml_enclose "val _ = " "" code_txt) |
|
47 |
|
48 fun output_ml ctxt code_txt = |
46 let |
49 let |
47 val srcpos = {delimited = false, text = (ml_val code_txt), pos = Position.none} |
50 val _ = ML_Context.eval_in (SOME ctxt) ML_Compiler.flags (Input.pos_of code_txt) (ml_val code_txt) |
48 in |
51 in |
49 (ML_Context.eval_source_in (SOME ctxt) ML_Compiler.flags srcpos; |
52 Pretty.str (Input.source_content code_txt) |
50 Thy_Output.output ctxt (map Pretty.str (space_explode "\n" code_txt))) |
53 end |
51 end |
54 |
52 |
55 val ml_checked_setup = Thy_Output.antiquotation_pretty_source @{binding "ML_checked"} (Scan.lift Args.text_input) output_ml*} |
53 val ml_checked_setup = Thy_Output.antiquotation @{binding "ML_checked"} (Scan.lift Args.name) output_ml*} |
|
54 |
56 |
55 setup {* ml_checked_setup *} |
57 setup {* ml_checked_setup *} |
|
58 |
56 |
59 |
57 text {* |
60 text {* |
58 The parser @{ML "(Scan.lift Args.name)"} in Line 7 parses a string, in this |
61 The parser @{ML "(Scan.lift Args.name)"} in Line 7 parses a string, in this |
59 case the code, and then calls the function @{ML output_ml}. As mentioned |
62 case the code, and then calls the function @{ML output_ml}. As mentioned |
60 before, the parsed code is sent to the ML-compiler in Line 4 using the |
63 before, the parsed code is sent to the ML-compiler in Line 4 using the |
61 function @{ML ml_val}, which constructs the appropriate ML-expression, and |
64 function @{ML ml_val}, which constructs the appropriate ML-expression, and |
62 using @{ML "eval_in" in ML_Context}, which calls the compiler. If the code is |
65 using @{ML "eval_in" in ML_Context}, which calls the compiler. If the code is |
63 ``approved'' by the compiler, then the output function @{ML "output" in |
66 ``approved'' by the compiler, then the output function @{ML "output" in |
64 Thy_Output} in the next line pretty prints the code. This function expects |
67 Document_Antiquotation} in the next line pretty prints the code. This function expects |
65 that the code is a list of (pretty)strings where each string correspond to a |
68 that the code is a list of (pretty)strings where each string correspond to a |
66 line in the output. Therefore the use of @{ML "(space_explode \"\\n\" txt)" |
69 line in the output. Therefore the use of @{ML "(space_explode \"\\n\" txt)" |
67 for txt} which produces such a list according to linebreaks. There are a |
70 for txt} which produces such a list according to linebreaks. There are a |
68 number of options for antiquotations that are observed by the function |
71 number of options for antiquotations that are observed by the function |
69 @{ML "output" in Thy_Output} when printing the code (including @{text "[display]"} |
72 @{ML "output" in Document_Antiquotation} when printing the code (including @{text "[display]"} |
70 and @{text "[quotes]"}). The function @{ML "antiquotation" in Thy_Output} in |
73 and @{text "[quotes]"}). The function @{ML "antiquotation_raw" in Thy_Output} in |
71 Line 7 sets up the new document antiquotation. |
74 Line 7 sets up the new document antiquotation. |
72 |
75 |
73 \begin{readmore} |
76 \begin{readmore} |
74 For more information about options of document antiquotations see \rsccite{sec:antiq}). |
77 For more information about options of document antiquotations see \rsccite{sec:antiq}). |
75 \end{readmore} |
78 \end{readmore} |
76 |
79 |
77 Since we used the argument @{ML "Position.none"}, the compiler cannot give specific |
80 Since we used the argument @{ML "Position.none"}, the compiler cannot give specific |
78 information about the line number, in case an error is detected. We |
81 information about the line number, in case an error is detected. We |
79 can improve the code above slightly by writing |
82 can improve the code above slightly by writing |
80 *} |
83 *} |
81 |
84 (* FIXME: remove |
82 ML%linenosgray{*fun output_ml {context = ctxt, ...} (code_txt, pos) = |
85 ML%linenosgray{*fun output_ml ctxt (code_txt, pos) = |
83 let |
86 let |
84 val srcpos = {delimited = false, pos = pos, text = ml_val code_txt} |
87 val srcpos = {delimited = false, pos = pos, text = ml_val code_txt} |
85 in |
88 in |
86 (ML_Context.eval_source_in (SOME ctxt) ML_Compiler.flags srcpos; |
89 (ML_Context.eval_source_in (SOME ctxt) ML_Compiler.flags srcpos; |
87 Thy_Output.output ctxt (map Pretty.str (space_explode "\n" code_txt))) |
90 code_txt |
|
91 |> space_explode "\n" |
|
92 |> map Pretty.str |
|
93 |> Pretty.list "" "" |
|
94 |> Document_Antiquotation.output ctxt |
|
95 |> Latex.string) |
88 end |
96 end |
89 |
97 |
90 val ml_checked_setup2 = Thy_Output.antiquotation @{binding "ML_checked2"} |
98 val ml_checked_setup2 = Thy_Output.antiquotation @{binding "ML_checked2"} |
91 (Scan.lift (Parse.position Args.name)) output_ml *} |
99 (Scan.lift (Parse.position Args.name)) output_ml *} |
92 |
100 |
93 setup {* ml_checked_setup2 *} |
101 setup {* ml_checked_setup2 *} |
94 |
102 *) |
95 text {* |
103 text {* |
96 where in Lines 1 and 2 the positional information is properly treated. The |
104 where in Lines 1 and 2 the positional information is properly treated. The |
97 parser @{ML Parse.position} encodes the positional information in the |
105 parser @{ML Parse.position} encodes the positional information in the |
98 result. |
106 result. |
99 |
107 |
100 We can now write @{text "@{ML_checked2 \"2 + 3\"}"} in a document in order to |
108 We can now write @{text "@{ML_checked2 \"2 + 3\"}"} in a document in order to |
101 obtain @{ML_checked2 "2 + 3"} and be sure that this code compiles until |
109 obtain @{ML_checked "2 + 3"} and be sure that this code compiles until |
102 somebody changes the definition of addition. |
110 somebody changes the definition of addition. |
103 |
111 |
104 |
112 |
105 The second document antiquotation we describe extends the first by a pattern |
113 The second document antiquotation we describe extends the first by a pattern |
106 that specifies what the result of the ML-code should be and checks the |
114 that specifies what the result of the ML-code should be and checks the |