| author | Christian Urban <urbanc@in.tum.de> |
| Thu, 10 Nov 2011 19:25:25 +0000 | |
| changeset 494 | 743020b817af |
| parent 493 | e3656cc81d27 |
| child 495 | f3f24874e8be |
| permissions | -rw-r--r-- |
|
395
2c392f61f400
spilt the Essential's chapter
Christian Urban <urbanc@in.tum.de>
parents:
394
diff
changeset
|
1 |
theory Advanced |
| 441 | 2 |
imports Base First_Steps |
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
3 |
begin |
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
4 |
|
|
346
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
5 |
(*<*) |
|
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
6 |
setup{*
|
|
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
7 |
open_file_with_prelude |
|
395
2c392f61f400
spilt the Essential's chapter
Christian Urban <urbanc@in.tum.de>
parents:
394
diff
changeset
|
8 |
"Advanced_Code.thy" |
| 441 | 9 |
["theory Advanced", "imports Base First_Steps", "begin"] |
|
346
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
10 |
*} |
|
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
11 |
(*>*) |
|
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
12 |
|
|
0fea8b7a14a1
tuned the ML-output mechanism; tuned slightly the text
Christian Urban <urbanc@in.tum.de>
parents:
345
diff
changeset
|
13 |
|
| 414 | 14 |
chapter {* Advanced Isabelle\label{chp:advanced} *}
|
|
381
97518188ef0e
added more to the unification section
Christian Urban <urbanc@in.tum.de>
parents:
380
diff
changeset
|
15 |
|
|
97518188ef0e
added more to the unification section
Christian Urban <urbanc@in.tum.de>
parents:
380
diff
changeset
|
16 |
text {*
|
| 410 | 17 |
\begin{flushright}
|
18 |
{\em All things are difficult before they are easy.} \\[1ex]
|
|
19 |
proverb |
|
20 |
\end{flushright}
|
|
21 |
||
22 |
\medskip |
|
| 400 | 23 |
While terms, types and theorems are the most basic data structures in |
24 |
Isabelle, there are a number of layers built on top of them. Most of these |
|
| 408 | 25 |
layers are concerned with storing and manipulating data. Handling them |
| 487 | 26 |
properly is an essential skill for programming on the ML-level of Isabelle. |
27 |
The most basic layer are theories. They contain global data and |
|
| 408 | 28 |
can be seen as the ``long-term memory'' of Isabelle. There is usually only |
29 |
one theory active at each moment. Proof contexts and local theories, on the |
|
| 400 | 30 |
other hand, store local data for a task at hand. They act like the |
| 408 | 31 |
``short-term memory'' and there can be many of them that are active in |
32 |
parallel. |
|
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
33 |
*} |
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
34 |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
35 |
section {* Theories and Setups\label{sec:theories} *}
|
| 358 | 36 |
|
37 |
text {*
|
|
| 492 | 38 |
Theories, as said above, are the most basic layer of abstraction in |
39 |
Isabelle. They record information about definitions, syntax declarations, axioms, |
|
| 488 | 40 |
theorems and much more. For example, if a definition is made, it |
41 |
must be stored in a theory in order to be usable later on. Similar |
|
42 |
with proofs: once a proof is finished, the proved theorem needs to |
|
43 |
be stored in the theorem database of the theory in order to be |
|
| 491 | 44 |
usable. All relevant data of a theory can be queried with the |
45 |
Isabelle command \isacommand{print\_theory}.
|
|
| 358 | 46 |
|
47 |
\begin{isabelle}
|
|
48 |
\isacommand{print\_theory}\\
|
|
49 |
@{text "> names: Pure Code_Generator HOL \<dots>"}\\
|
|
50 |
@{text "> classes: Inf < type \<dots>"}\\
|
|
51 |
@{text "> default sort: type"}\\
|
|
52 |
@{text "> syntactic types: #prop \<dots>"}\\
|
|
53 |
@{text "> logical types: 'a \<times> 'b \<dots>"}\\
|
|
54 |
@{text "> type arities: * :: (random, random) random \<dots>"}\\
|
|
55 |
@{text "> logical constants: == :: 'a \<Rightarrow> 'a \<Rightarrow> prop \<dots>"}\\
|
|
56 |
@{text "> abbreviations: \<dots>"}\\
|
|
57 |
@{text "> axioms: \<dots>"}\\
|
|
58 |
@{text "> oracles: \<dots>"}\\
|
|
59 |
@{text "> definitions: \<dots>"}\\
|
|
60 |
@{text "> theorems: \<dots>"}
|
|
61 |
\end{isabelle}
|
|
62 |
||
| 487 | 63 |
Functions acting on theories often end with the suffix @{text "_global"},
|
64 |
for example the function @{ML read_term_global in Syntax} in the structure
|
|
65 |
@{ML_struct Syntax}. The reason is to set them syntactically apart from
|
|
| 491 | 66 |
functions acting on contexts or local theories, which will be discussed in |
67 |
the next sections. There is a tendency amongst Isabelle developers to prefer |
|
| 487 | 68 |
``non-global'' operations, because they have some advantages, as we will also |
| 490 | 69 |
discuss later. However, some basic understanding of theories is still necessary |
70 |
for effective Isabelle programming. |
|
| 487 | 71 |
|
| 491 | 72 |
An important Isabelle command with theories is \isacommand{setup}. In the
|
| 492 | 73 |
previous chapters we used it already to make a theorem attribute known |
74 |
to Isabelle and to register a theorem under a name. What happens behind the |
|
| 490 | 75 |
scenes is that \isacommand{setup} expects a function of type @{ML_type
|
76 |
"theory -> theory"}: the input theory is the current theory and the output |
|
77 |
the theory where the attribute has been registered or the theorem has been |
|
78 |
stored. This is a fundamental principle in Isabelle. A similar situation |
|
| 491 | 79 |
arises with declaring a constant, which can be done on the ML-level with |
80 |
function @{ML_ind declare_const in Sign} from the structure @{ML_struct
|
|
| 490 | 81 |
Sign}. To see how \isacommand{setup} works, consider the following code:
|
82 |
||
| 348 | 83 |
*} |
84 |
||
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
85 |
ML{*let
|
|
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
86 |
val thy = @{theory}
|
|
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
87 |
val bar_const = ((@{binding "BAR"}, @{typ "nat"}), NoSyn)
|
|
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
88 |
in |
|
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
89 |
Sign.declare_const @{context} bar_const thy
|
|
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
90 |
end*} |
| 348 | 91 |
|
92 |
text {*
|
|
| 488 | 93 |
If you simply run this code\footnote{Recall that ML-code needs to be enclosed in
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
94 |
\isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}.} with the
|
| 491 | 95 |
intention of declaring a constant @{text "BAR"} having type @{typ nat}, then
|
| 488 | 96 |
indeed you obtain a theory as result. But if you query the |
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
97 |
constant on the Isabelle level using the command \isacommand{term}
|
| 348 | 98 |
|
99 |
\begin{isabelle}
|
|
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
100 |
\isacommand{term}~@{text BAR}\\
|
| 348 | 101 |
@{text "> \"BAR\" :: \"'a\""}
|
102 |
\end{isabelle}
|
|
103 |
||
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
104 |
you can see that you do \emph{not} obtain a constant of type @{typ nat}, but a free
|
| 484 | 105 |
variable (printed in blue) of polymorphic type. The problem is that the |
106 |
ML-expression above did not ``register'' the declaration with the current theory. |
|
107 |
This is what the command \isacommand{setup} is for. The constant is properly
|
|
108 |
declared with |
|
| 348 | 109 |
*} |
110 |
||
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
111 |
setup %gray {* fn thy =>
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
112 |
let |
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
113 |
val bar_const = ((@{binding "BAR"}, @{typ "nat"}), NoSyn)
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
114 |
val (_, thy') = Sign.declare_const @{context} bar_const thy
|
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
115 |
in |
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
116 |
thy' |
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
117 |
end *} |
| 348 | 118 |
|
119 |
text {*
|
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
120 |
where the declaration is actually applied to the current theory and |
| 348 | 121 |
|
122 |
\begin{isabelle}
|
|
123 |
\isacommand{term}~@{text [quotes] "BAR"}\\
|
|
124 |
@{text "> \"BAR\" :: \"nat\""}
|
|
125 |
\end{isabelle}
|
|
126 |
||
| 492 | 127 |
now returns a (black) constant with the type @{typ nat}, as expected.
|
| 348 | 128 |
|
| 491 | 129 |
In a sense, \isacommand{setup} can be seen as a transaction that
|
130 |
takes the current theory @{text thy}, applies an operation, and
|
|
131 |
produces a new current theory @{text thy'}. This means that we have
|
|
132 |
to be careful to apply operations always to the most current theory, |
|
133 |
not to a \emph{stale} one. Consider again the function inside the
|
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
134 |
\isacommand{setup}-command:
|
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
135 |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
136 |
\begin{isabelle}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
137 |
\begin{graybox}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
138 |
\isacommand{setup}~@{text "\<verbopen>"} @{ML
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
139 |
"fn thy => |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
140 |
let |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
141 |
val bar_const = ((@{binding \"BAR\"}, @{typ \"nat\"}), NoSyn)
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
142 |
val (_, thy') = Sign.declare_const @{context} bar_const thy
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
143 |
in |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
144 |
thy |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
145 |
end"}~@{text "\<verbclose>"}\isanewline
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
146 |
@{text "> ERROR \"Stale theory encountered\""}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
147 |
\end{graybox}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
148 |
\end{isabelle}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
149 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
150 |
This time we erroneously return the original theory @{text thy}, instead of
|
| 488 | 151 |
the modified one @{text thy'}. Such buggy code will always result into
|
152 |
a runtime error message about stale theories. |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
153 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
154 |
However, sometimes it does make sense to work with two theories at the same |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
155 |
time, especially in the context of parsing and typing. In the code below we |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
156 |
use in Line 3 the function @{ML_ind copy in Theory} from the structure
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
157 |
@{ML_struct Theory} for obtaining a new theory that contains the same
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
158 |
data, but is unrelated to the existing theory. |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
159 |
*} |
|
485
f3536f0b47a9
added section about testboard
Christian Urban <urbanc@in.tum.de>
parents:
484
diff
changeset
|
160 |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
161 |
setup %graylinenos {* fn thy =>
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
162 |
let |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
163 |
val tmp_thy = Theory.copy thy |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
164 |
val foo_const = ((@{binding "FOO"}, @{typ "nat => nat"}), NoSyn)
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
165 |
val (_, tmp_thy') = Sign.declare_const @{context} foo_const tmp_thy
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
166 |
val trm1 = Syntax.read_term_global tmp_thy' "FOO baz" |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
167 |
val trm2 = Syntax.read_term_global thy "FOO baz" |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
168 |
val _ = writeln (@{make_string} trm1 ^ "\n" ^ @{make_string} trm2)
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
169 |
in |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
170 |
thy |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
171 |
end *} |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
172 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
173 |
text {*
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
174 |
That means we can make changes to the theory @{text tmp_thy} without
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
175 |
affecting the current theory @{text thy}. In this case we declare in @{text
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
176 |
"tmp_thy"} the constant @{text FOO} (Lines 4 and 5). The point of this code
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
177 |
is that we next, in Lines 6 and 7, parse a string to become a term (both |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
178 |
times the string is @{text [quotes] "FOO baz"}). But since we parse the string
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
179 |
once in the context of the theory @{text tmp_thy'} in which @{text FOO} is
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
180 |
declared to be a constant of type @{typ "nat \<Rightarrow>nat"} and once in the context
|
| 488 | 181 |
of @{text thy} where it is not, we obtain two different terms, namely
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
182 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
183 |
\begin{isabelle}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
184 |
\begin{graybox}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
185 |
@{text "> Const (\"Advanced.FOO\", \"nat \<Rightarrow> nat\") $ Free (\"baz\", \"nat\")"}\isanewline
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
186 |
@{text "> Free (\"FOO\", \"'a \<Rightarrow> 'b\") $ Free (\"baz\", \"'a\")"}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
187 |
\end{graybox}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
188 |
\end{isabelle}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
189 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
190 |
There are two reasons for parsing a term in a temporary theory. One is to |
| 488 | 191 |
obtain fully qualified names for constants and the other is appropriate type |
192 |
inference. This is relevant in situations where definitions are made later, |
|
193 |
but parsing and type inference has to take already proceed as if the definitions |
|
194 |
were already made. |
|
| 348 | 195 |
*} |
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
196 |
|
|
341
62dea749d5ed
more work on theorem section
Christian Urban <urbanc@in.tum.de>
parents:
340
diff
changeset
|
197 |
section {* Contexts (TBD) *}
|
|
62dea749d5ed
more work on theorem section
Christian Urban <urbanc@in.tum.de>
parents:
340
diff
changeset
|
198 |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
199 |
text {*
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
200 |
Contexts are arguably more important than theories, even though they only |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
201 |
contain ``short-term memory data''. The reason is that a vast number of |
| 490 | 202 |
functions in Isabelle depend in one way or another on contexts. Even such |
203 |
mundane operations like printing out a term make essential use of contexts. |
|
| 494 | 204 |
For this consider the following contrived proof-snippet whose purpose is to |
| 490 | 205 |
fix two variables: |
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
206 |
*} |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
207 |
|
| 488 | 208 |
lemma "True" |
209 |
proof - |
|
| 491 | 210 |
txt_raw {*\mbox{}\\[-7mm]*}
|
| 492 | 211 |
ML_prf {* Variable.dest_fixes @{context} *}
|
| 491 | 212 |
txt_raw {*\mbox{}\\[-7mm]\mbox{}*}
|
| 492 | 213 |
fix x y |
| 491 | 214 |
txt_raw {*\mbox{}\\[-7mm]*}
|
| 488 | 215 |
ML_prf {* Variable.dest_fixes @{context} *}
|
| 491 | 216 |
txt_raw {*\mbox{}\\[-7mm] \ldots*}(*<*)oops(*>*)
|
| 488 | 217 |
|
| 490 | 218 |
text {*
|
219 |
The interesting point in this proof is that we injected ML-code before and after |
|
220 |
the variables are fixed. For this remember that ML-code inside a proof |
|
| 494 | 221 |
needs to be enclosed inside \isacommand{ML\_prf}~@{text "\<verbopen> \<dots> \<verbclose>"},
|
| 490 | 222 |
not \isacommand{ML}~@{text "\<verbopen> \<dots> \<verbclose>"}. The function
|
223 |
@{ML_ind dest_fixes in Variable} from the structure @{ML_struct Variable} takes
|
|
224 |
a context and returns all its currently fixed variable (names). That |
|
225 |
means a context has a dataslot containing information about fixed variables. |
|
226 |
The ML-antiquotation @{text "@{context}"} points to the context that is
|
|
227 |
active at that point of the theory. Consequently, in the first call to |
|
228 |
@{ML dest_fixes in Variable} this dataslot is empty; in the second it is
|
|
229 |
filled with @{text x} and @{text y}. What is interesting is that contexts
|
|
| 494 | 230 |
can be stacked. For this consider the following proof fragment: |
| 490 | 231 |
*} |
232 |
||
233 |
lemma "True" |
|
234 |
proof - |
|
235 |
fix x y |
|
236 |
{ fix z w
|
|
| 491 | 237 |
txt_raw {*\mbox{}\\[-7mm]*}
|
238 |
ML_prf {* Variable.dest_fixes @{context} *}
|
|
| 492 | 239 |
txt_raw {*\mbox{}\\[-7mm]\mbox{}*}
|
240 |
} |
|
| 491 | 241 |
txt_raw {*\mbox{}\\[-7mm]*}
|
| 490 | 242 |
ML_prf {* Variable.dest_fixes @{context} *}
|
| 491 | 243 |
txt_raw {*\mbox{}\\[-7mm] \ldots*}(*<*)oops(*>*)
|
244 |
||
245 |
text {*
|
|
| 492 | 246 |
The first time we call @{ML dest_fixes in Variable} we have four fixes variables;
|
247 |
the second time we get only the fixes variables @{text x} and @{text y} as answer.
|
|
248 |
This means the curly-braces act as opening and closing statements for a context. |
|
| 491 | 249 |
The above proof corresoponds roughly to the following ML-code. |
250 |
*} |
|
| 488 | 251 |
|
| 492 | 252 |
ML{*val ctxt0 = @{context};
|
253 |
val ([x, y], ctxt1) = Variable.add_fixes ["x", "y"] ctxt0; |
|
254 |
val ([z, w], ctxt2) = Variable.add_fixes ["z", "w"] ctxt1*} |
|
255 |
||
256 |
text {*
|
|
| 494 | 257 |
where the function @{ML_ind add_fixes in Variable} fixes a list of variables
|
258 |
specified by strings. Let us come back to the point about printing terms. Consider |
|
259 |
printing out the term @{text "(x, y, z, w)"} using the function @{ML_ind pretty_term}.
|
|
260 |
This function takes a term and a context as argument. |
|
| 492 | 261 |
*} |
262 |
||
| 493 | 263 |
ML {*
|
264 |
let |
|
| 494 | 265 |
val trm = @{term "(x, y, z, w)"}
|
| 493 | 266 |
in |
267 |
pwriteln (Pretty.chunks |
|
268 |
[ pretty_term ctxt0 trm, |
|
269 |
pretty_term ctxt1 trm, |
|
270 |
pretty_term ctxt2 trm ]) |
|
271 |
end |
|
272 |
*} |
|
273 |
||
274 |
||
275 |
text {*
|
|
| 494 | 276 |
The term we are printing is in all three cases the same---a tuple containing four |
277 |
free variables. As you can see in case of @{ML "ctxt0"}, however, all variables are highlighted
|
|
278 |
indicating a problem, while in case of @{ML "ctxt1"} @{text x} and @{text y} are printed
|
|
279 |
as normal (blue) free variables, but not @{text z} and @{text w}. In the last case all
|
|
280 |
variables are printed as expected. The point is that the context contains the information |
|
281 |
which variables are fixed, and designates all other free variables as being alien or faulty. |
|
282 |
While this seems like a minor feat, the concept of making the context aware of |
|
283 |
fixed variables is actually quite useful. For example it prevents us from fixing a |
|
284 |
variable twice |
|
285 |
||
286 |
@{ML_response_fake [gray, display]
|
|
287 |
"@{context}
|
|
288 |
|> Variable.add_fixes [\"x\", \"y\"] |
|
289 |
||>> Variable.add_fixes [\"x\", \"y\"]" |
|
290 |
"Duplicate fixed variable(s): \"x\""} |
|
| 493 | 291 |
*} |
292 |
||
| 492 | 293 |
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
294 |
(* |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
295 |
ML{*Proof_Context.debug := true*}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
296 |
ML{*Proof_Context.verbose := true*}
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
297 |
*) |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
298 |
|
| 487 | 299 |
(* |
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
300 |
lemma "True" |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
301 |
proof - |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
302 |
{ -- "\<And>x. _"
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
303 |
fix x |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
304 |
have "B x" sorry |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
305 |
thm this |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
306 |
} |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
307 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
308 |
thm this |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
309 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
310 |
{ -- "A \<Longrightarrow> _"
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
311 |
assume A |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
312 |
have B sorry |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
313 |
thm this |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
314 |
} |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
315 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
316 |
thm this |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
317 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
318 |
{ -- "\<And>x. x = _ \<Longrightarrow> _"
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
319 |
def x \<equiv> a |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
320 |
have "B x" sorry |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
321 |
} |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
322 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
323 |
thm this |
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
324 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
325 |
oops |
| 487 | 326 |
*) |
| 413 | 327 |
|
|
341
62dea749d5ed
more work on theorem section
Christian Urban <urbanc@in.tum.de>
parents:
340
diff
changeset
|
328 |
section {* Local Theories (TBD) *}
|
|
62dea749d5ed
more work on theorem section
Christian Urban <urbanc@in.tum.de>
parents:
340
diff
changeset
|
329 |
|
| 394 | 330 |
text {*
|
| 400 | 331 |
In contrast to an ordinary theory, which simply consists of a type |
332 |
signature, as well as tables for constants, axioms and theorems, a local |
|
333 |
theory contains additional context information, such as locally fixed |
|
334 |
variables and local assumptions that may be used by the package. The type |
|
335 |
@{ML_type local_theory} is identical to the type of \emph{proof contexts}
|
|
336 |
@{ML_type "Proof.context"}, although not every proof context constitutes a
|
|
337 |
valid local theory. |
|
338 |
||
339 |
@{ML "Context.>> o Context.map_theory"}
|
|
| 394 | 340 |
@{ML_ind "Local_Theory.declaration"}
|
|
486
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
341 |
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
342 |
A similar command is \isacommand{local\_setup}, which expects a function
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
343 |
of type @{ML_type "local_theory -> local_theory"}. Later on we will also
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
344 |
use the commands \isacommand{method\_setup} for installing methods in the
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
345 |
current theory and \isacommand{simproc\_setup} for adding new simprocs to
|
|
45cfd2ece7bd
a section about theories and setups
Christian Urban <urbanc@in.tum.de>
parents:
485
diff
changeset
|
346 |
the current simpset. |
| 394 | 347 |
*} |
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
348 |
|
|
336
a12bb28fe2bd
polished on the pretty printing section
Christian Urban <urbanc@in.tum.de>
parents:
335
diff
changeset
|
349 |
|
| 394 | 350 |
section {* Morphisms (TBD) *}
|
351 |
||
352 |
text {*
|
|
353 |
Morphisms are arbitrary transformations over terms, types, theorems and bindings. |
|
354 |
They can be constructed using the function @{ML_ind morphism in Morphism},
|
|
355 |
which expects a record with functions of type |
|
356 |
||
357 |
\begin{isabelle}
|
|
358 |
\begin{tabular}{rl}
|
|
359 |
@{text "binding:"} & @{text "binding -> binding"}\\
|
|
360 |
@{text "typ:"} & @{text "typ -> typ"}\\
|
|
361 |
@{text "term:"} & @{text "term -> term"}\\
|
|
362 |
@{text "fact:"} & @{text "thm list -> thm list"}
|
|
363 |
\end{tabular}
|
|
364 |
\end{isabelle}
|
|
365 |
||
366 |
The simplest morphism is the @{ML_ind identity in Morphism}-morphism defined as
|
|
367 |
*} |
|
368 |
||
| 481 | 369 |
ML{*val identity = Morphism.morphism {binding = [], typ = [], term = [], fact = []}*}
|
| 394 | 370 |
|
371 |
text {*
|
|
372 |
Morphisms can be composed with the function @{ML_ind "$>" in Morphism}
|
|
373 |
*} |
|
374 |
||
375 |
ML{*fun trm_phi (Free (x, T)) = Var ((x, 0), T)
|
|
376 |
| trm_phi (Abs (x, T, t)) = Abs (x, T, trm_phi t) |
|
377 |
| trm_phi (t $ s) = (trm_phi t) $ (trm_phi s) |
|
378 |
| trm_phi t = t*} |
|
379 |
||
380 |
ML{*val phi = Morphism.term_morphism trm_phi*}
|
|
381 |
||
382 |
ML{*Morphism.term phi @{term "P x y"}*}
|
|
383 |
||
384 |
text {*
|
|
385 |
@{ML_ind term_morphism in Morphism}
|
|
386 |
||
387 |
@{ML_ind term in Morphism},
|
|
388 |
@{ML_ind thm in Morphism}
|
|
389 |
||
390 |
\begin{readmore}
|
|
391 |
Morphisms are implemented in the file @{ML_file "Pure/morphism.ML"}.
|
|
392 |
\end{readmore}
|
|
393 |
*} |
|
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
394 |
|
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
395 |
section {* Misc (TBD) *}
|
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
396 |
|
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
397 |
ML {*Datatype.get_info @{theory} "List.list"*}
|
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
398 |
|
|
319
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
399 |
text {*
|
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
400 |
FIXME: association lists: |
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
401 |
@{ML_file "Pure/General/alist.ML"}
|
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
402 |
|
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
403 |
FIXME: calling the ML-compiler |
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
404 |
|
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
405 |
*} |
|
6bce4acf7f2a
added file for producing a keyword file
Christian Urban <urbanc@in.tum.de>
parents:
318
diff
changeset
|
406 |
|
| 414 | 407 |
section {* What Is In an Isabelle Name? (TBD) *}
|
408 |
||
409 |
text {*
|
|
410 |
On the ML-level of Isabelle, you often have to work with qualified names. |
|
411 |
These are strings with some additional information, such as positional |
|
412 |
information and qualifiers. Such qualified names can be generated with the |
|
413 |
antiquotation @{text "@{binding \<dots>}"}. For example
|
|
414 |
||
415 |
@{ML_response [display,gray]
|
|
416 |
"@{binding \"name\"}"
|
|
417 |
"name"} |
|
418 |
||
419 |
An example where a qualified name is needed is the function |
|
420 |
@{ML_ind define in Local_Theory}. This function is used below to define
|
|
421 |
the constant @{term "TrueConj"} as the conjunction @{term "True \<and> True"}.
|
|
422 |
*} |
|
423 |
||
424 |
local_setup %gray {*
|
|
425 |
Local_Theory.define ((@{binding "TrueConj"}, NoSyn),
|
|
426 |
(Attrib.empty_binding, @{term "True \<and> True"})) #> snd *}
|
|
427 |
||
428 |
text {*
|
|
429 |
Now querying the definition you obtain: |
|
430 |
||
431 |
\begin{isabelle}
|
|
432 |
\isacommand{thm}~@{text "TrueConj_def"}\\
|
|
433 |
@{text "> "}~@{thm TrueConj_def}
|
|
434 |
\end{isabelle}
|
|
435 |
||
436 |
\begin{readmore}
|
|
437 |
The basic operations on bindings are implemented in |
|
438 |
@{ML_file "Pure/General/binding.ML"}.
|
|
439 |
\end{readmore}
|
|
440 |
||
441 |
\footnote{\bf FIXME give a better example why bindings are important}
|
|
442 |
\footnote{\bf FIXME give a pointer to \isacommand{local\_setup}; if not, then explain
|
|
443 |
why @{ML snd} is needed.}
|
|
444 |
\footnote{\bf FIXME: There should probably a separate section on binding, long-names
|
|
445 |
and sign.} |
|
446 |
||
447 |
*} |
|
448 |
||
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
449 |
|
| 360 | 450 |
ML {* Sign.intern_type @{theory} "list" *}
|
451 |
ML {* Sign.intern_const @{theory} "prod_fun" *}
|
|
452 |
||
| 414 | 453 |
text {*
|
454 |
\footnote{\bf FIXME: Explain the following better; maybe put in a separate
|
|
455 |
section and link with the comment in the antiquotation section.} |
|
456 |
||
457 |
Occasionally you have to calculate what the ``base'' name of a given |
|
| 462 | 458 |
constant is. For this you can use the function @{ML_ind Long_Name.base_name}. For example:
|
| 414 | 459 |
|
| 462 | 460 |
@{ML_response [display,gray] "Long_Name.base_name \"List.list.Nil\"" "\"Nil\""}
|
| 414 | 461 |
|
462 |
\begin{readmore}
|
|
463 |
Functions about naming are implemented in @{ML_file "Pure/General/name_space.ML"};
|
|
464 |
functions about signatures in @{ML_file "Pure/sign.ML"}.
|
|
465 |
\end{readmore}
|
|
466 |
*} |
|
|
387
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
467 |
|
|
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
468 |
text {*
|
|
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
469 |
@{ML_ind "Binding.name_of"} returns the string without markup
|
| 394 | 470 |
|
471 |
@{ML_ind "Binding.conceal"}
|
|
|
387
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
472 |
*} |
|
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
473 |
|
|
388
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
474 |
section {* Concurrency (TBD) *}
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
475 |
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
476 |
text {*
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
477 |
@{ML_ind prove_future in Goal}
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
478 |
@{ML_ind future_result in Goal}
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
479 |
@{ML_ind fork_pri in Future}
|
|
0b337dedc306
added Skip_Proof.mk_thm and some pointers about concurrency
Christian Urban <urbanc@in.tum.de>
parents:
387
diff
changeset
|
480 |
*} |
|
387
5dcee4d751ad
completed the unification section
Christian Urban <urbanc@in.tum.de>
parents:
386
diff
changeset
|
481 |
|
| 396 | 482 |
section {* Parse and Print Translations (TBD) *}
|
483 |
||
|
349
9e374cd891e1
updated to Isabelle changes
Christian Urban <urbanc@in.tum.de>
parents:
348
diff
changeset
|
484 |
section {* Summary *}
|
|
9e374cd891e1
updated to Isabelle changes
Christian Urban <urbanc@in.tum.de>
parents:
348
diff
changeset
|
485 |
|
|
9e374cd891e1
updated to Isabelle changes
Christian Urban <urbanc@in.tum.de>
parents:
348
diff
changeset
|
486 |
text {*
|
|
395
2c392f61f400
spilt the Essential's chapter
Christian Urban <urbanc@in.tum.de>
parents:
394
diff
changeset
|
487 |
TBD |
|
349
9e374cd891e1
updated to Isabelle changes
Christian Urban <urbanc@in.tum.de>
parents:
348
diff
changeset
|
488 |
*} |
|
318
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
489 |
|
|
efb5fff99c96
split up the first-steps section into two chapters
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
|
490 |
end |