159 *} |
159 *} |
160 |
160 |
161 setup %graylinenos {* fn thy => |
161 setup %graylinenos {* fn thy => |
162 let |
162 let |
163 val tmp_thy = Theory.copy thy |
163 val tmp_thy = Theory.copy thy |
164 val foo_const = ((@{binding "FOO"}, @{typ "nat => nat"}), NoSyn) |
164 val foo_const = ((@{binding "FOO"}, @{typ "nat \<Rightarrow> nat"}), NoSyn) |
165 val (_, tmp_thy') = Sign.declare_const @{context} foo_const tmp_thy |
165 val (_, tmp_thy') = Sign.declare_const @{context} foo_const tmp_thy |
166 val trm1 = Syntax.read_term_global tmp_thy' "FOO baz" |
166 val trm1 = Syntax.read_term_global tmp_thy' "FOO baz" |
167 val trm2 = Syntax.read_term_global thy "FOO baz" |
167 val trm2 = Syntax.read_term_global thy "FOO baz" |
168 val _ = writeln (@{make_string} trm1 ^ "\n" ^ @{make_string} trm2) |
168 val _ = writeln (@{make_string} trm1 ^ "\n" ^ @{make_string} trm2) |
169 in |
169 in |
257 text {* |
257 text {* |
258 where the function @{ML_ind add_fixes in Variable} fixes a list of variables |
258 where the function @{ML_ind add_fixes in Variable} fixes a list of variables |
259 specified by strings. Let us come back to the point about printing terms. Consider |
259 specified by strings. Let us come back to the point about printing terms. Consider |
260 printing out the term \mbox{@{text "(x, y, z, w)"}} using our function @{ML_ind pretty_term}. |
260 printing out the term \mbox{@{text "(x, y, z, w)"}} using our function @{ML_ind pretty_term}. |
261 This function takes a term and a context as argument. Notice how the printing |
261 This function takes a term and a context as argument. Notice how the printing |
262 of the term changes with which context is used. |
262 of the term changes according to which context is used. |
263 |
263 |
264 \begin{isabelle} |
264 \begin{isabelle} |
265 \begin{graybox} |
265 \begin{graybox} |
266 @{ML "let |
266 @{ML "let |
267 val trm = @{term \"(x, y, z, w)\"} |
267 val trm = @{term \"(x, y, z, w)\"} |
296 are printed as expected. The point of this example is that the context |
296 are printed as expected. The point of this example is that the context |
297 contains the information which variables are fixed, and designates all other |
297 contains the information which variables are fixed, and designates all other |
298 free variables as being alien or faulty. Therefore the highlighting. |
298 free variables as being alien or faulty. Therefore the highlighting. |
299 While this seems like a minor detail, the concept of making the context aware |
299 While this seems like a minor detail, the concept of making the context aware |
300 of fixed variables is actually quite useful. For example it prevents us from |
300 of fixed variables is actually quite useful. For example it prevents us from |
301 fixing a variable twice |
301 fixing a variable twice. |
302 |
302 |
303 @{ML_response_fake [gray, display] |
303 @{ML_response_fake [gray, display] |
304 "@{context} |
304 "@{context} |
305 |> Variable.add_fixes [\"x\", \"x\"]" |
305 |> Variable.add_fixes [\"x\", \"x\"]" |
306 "ERROR: Duplicate fixed variable(s): \"x\""} |
306 "ERROR: Duplicate fixed variable(s): \"x\""} |
307 |
307 |
308 More importantly it also allows us to easily create fresh free variables avoiding any |
308 More importantly it also allows us to easily create fresh free variables avoiding any |
309 clashes with fixed variables. In Line~3 below we fix the variable @{text x} in the context |
309 clashes with fixed variables. In Line~3 below we fix the variable @{text x} in the context |
310 @{text ctxt1}. Next we want to create two fresh variables of type @{typ nat} |
310 @{text ctxt1}. Next we want to create two fresh variables of type @{typ nat} |
311 as variants of the string @{text [quotes] "x"}. |
311 as variants of the string @{text [quotes] "x"} (Lines 6 and 7). |
312 |
312 |
313 @{ML_response_fake [display, gray, linenos] |
313 @{ML_response_fake [display, gray, linenos] |
314 "let |
314 "let |
315 val ctxt0 = @{context} |
315 val ctxt0 = @{context} |
316 val (_, ctxt1) = Variable.add_fixes [\"x\"] ctxt0 |
316 val (_, ctxt1) = Variable.add_fixes [\"x\"] ctxt0 |
338 Variable.variant_frees ctxt1 [] frees |
338 Variable.variant_frees ctxt1 [] frees |
339 end" |
339 end" |
340 "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"} |
340 "[(\"xb\", \"nat\"), (\"xc\", \"nat\")]"} |
341 |
341 |
342 The result is @{text xb} and @{text xc} for the names of the fresh |
342 The result is @{text xb} and @{text xc} for the names of the fresh |
343 variables. Note that @{ML_ind declare_term in Variable} does not fix the |
343 variables, since @{text x} and @{text xa} occur in the term we declared. |
344 variables; it just makes them ``known'' to the context. This is helpful when |
344 Note that @{ML_ind declare_term in Variable} does not fix the |
345 parsing terms using the function @{ML_ind read_term in Syntax} from the |
345 variables; it just makes them ``known'' to the context. You can see |
346 structure @{ML_struct Syntax}. Consider the following code: |
346 that if you print out a declared term. |
|
347 |
|
348 \begin{isabelle} |
|
349 \begin{graybox} |
|
350 @{ML "let |
|
351 val trm = @{term \"P x y z\"} |
|
352 val ctxt1 = Variable.declare_term trm @{context} |
|
353 in |
|
354 pwriteln (pretty_term ctxt1 trm) |
|
355 end"}\\ |
|
356 \setlength{\fboxsep}{0mm} |
|
357 @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~% |
|
358 \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text x}}}~% |
|
359 \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text y}}}~% |
|
360 \colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text z}}} |
|
361 \end{graybox} |
|
362 \end{isabelle} |
|
363 |
|
364 All variables are highligted, indicating that they are not |
|
365 fixed. However, declaring a term is helpful when parsing terms using |
|
366 the function @{ML_ind read_term in Syntax} from the structure |
|
367 @{ML_struct Syntax}. Consider the following code: |
347 |
368 |
348 @{ML_response_fake [gray, display] |
369 @{ML_response_fake [gray, display] |
349 "let |
370 "let |
350 val ctxt0 = @{context} |
371 val ctxt0 = @{context} |
351 val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0 |
372 val ctxt1 = Variable.declare_term @{term \"x::nat\"} ctxt0 |
391 @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~% |
412 @{text ">"}~\colorbox{gray!5}{\raisebox{0mm}[3mm][1mm]{@{text P}}}~% |
392 @{text "?x ?y ?z"} |
413 @{text "?x ?y ?z"} |
393 \end{graybox} |
414 \end{graybox} |
394 \end{isabelle} |
415 \end{isabelle} |
395 |
416 |
396 In Line 3 we fix the variables @{term x}, @{term y} and @{term z} in context @{text ctxt1}. |
417 In Line 3 we fix the variables @{term x}, @{term y} and @{term z} in |
397 The function @{ML_ind export_terms in Variable} from the @{ML_struct Variable} can be used |
418 context @{text ctxt1}. The function @{ML_ind export_terms in |
398 to ``transfer'' terms between contexts. Transferring means to turn all (free) variables that |
419 Variable} from the @{ML_struct Variable} can be used to ``transfer'' |
399 are fixed in one context, but not in the other, into schematic variables. In our example |
420 terms between contexts. Transferring means to turn all (free) |
400 we are transferring the term @{text "P x y z"} from context @{text "ctxt1"} into @{text "ctxt0"} |
421 variables that are fixed in one context, but not in the other, into |
401 which means @{term x}, @{term y} and @{term z} become schematic variables (as can be seen |
422 schematic variables. In our example, we are transferring the term |
402 by the leading question mark). Note that the variable @{text P} stays a free variable, since |
423 @{text "P x y z"} from context @{text "ctxt1"} to @{text "ctxt0"}, |
403 it not fixed in @{text ctxt1}; it is even highlighed, because @{text "ctxt0"} does not |
424 which means @{term x}, @{term y} and @{term z} become schematic |
404 know about it. Note also that in Line 6 we had to use the function @{ML_ind singleton}, |
425 variables (as can be seen by the leading question marks). Note that |
405 because the function @{ML_ind export_terms in Variable} normally works over lists of terms. |
426 the variable @{text P} stays a free variable, since it not fixed in |
406 |
427 @{text ctxt1}; it is even highlighed, because @{text "ctxt0"} does |
407 |
428 not know about it. Note also that in Line 6 we had to use the |
408 *} |
429 function @{ML_ind singleton}, because the function @{ML_ind |
409 |
430 export_terms in Variable} normally works over lists of terms. |
410 ML {* |
431 |
411 let |
432 The case of transferring theorems is even more useful. The reason is |
|
433 that the generalisation of fixed variables to schematic variables is |
|
434 not trivial. For illustration purposes we use in the following code |
|
435 the function @{ML_ind make_thm in Skip_Proof} from the structure |
|
436 @{ML_struct Skip_Proof} in order to turn an arbitray term into a |
|
437 theorem. |
|
438 |
|
439 @{ML_response_fake [display, gray] |
|
440 "let |
|
441 val thy = @{theory} |
412 val ctxt0 = @{context} |
442 val ctxt0 = @{context} |
413 val (_, ctxt1) = Variable.add_fixes ["x", "y", "z"] ctxt0 |
443 val (_, ctxt1) = Variable.add_fixes [\"x\", \"y\", \"z\"] ctxt0 |
414 val foo_trm = @{term "P x y z"} |
444 val foo_thm = Skip_Proof.make_thm thy @{prop \"P x y z x y z\"} |
415 in |
445 in |
416 singleton (Variable.export_terms ctxt1 ctxt0) foo_trm |
446 singleton (Proof_Context.export ctxt1 ctxt0) foo_thm |
417 |> pretty_term ctxt1 |
447 end" |
418 |> pwriteln |
448 "> P ?x ?y ?z ?x ?y ?z"} |
419 end |
449 *} |
420 *} |
450 |
421 |
451 |
422 ML {* |
452 ML {* |
423 let |
453 let |
424 val thy = @{theory} |
454 val thy = @{theory} |
425 val ctxt0 = @{context} |
455 val ctxt0 = @{context} |