author | wenzelm |
Wed, 19 Feb 2020 20:00:07 +0100 | |
changeset 71460 | 8f628d216ea1 |
parent 69597 | ff784d5a5bfb |
child 72060 | efb7fd4a6d1f |
permissions | -rw-r--r-- |
61656 | 1 |
(*:maxLineLen=78:*) |
2 |
||
29755 | 3 |
theory Prelim |
4 |
imports Base |
|
5 |
begin |
|
18537 | 6 |
|
58618 | 7 |
chapter \<open>Preliminaries\<close> |
18537 | 8 |
|
58618 | 9 |
section \<open>Contexts \label{sec:context}\<close> |
18537 | 10 |
|
58618 | 11 |
text \<open> |
61854 | 12 |
A logical context represents the background that is required for formulating |
13 |
statements and composing proofs. It acts as a medium to produce formal |
|
14 |
content, depending on earlier material (declarations, results etc.). |
|
18537 | 15 |
|
61854 | 16 |
For example, derivations within the Isabelle/Pure logic can be described as |
17 |
a judgment \<open>\<Gamma> \<turnstile>\<^sub>\<Theta> \<phi>\<close>, which means that a proposition \<open>\<phi>\<close> is derivable from |
|
18 |
hypotheses \<open>\<Gamma>\<close> within the theory \<open>\<Theta>\<close>. There are logical reasons for keeping |
|
19 |
\<open>\<Theta>\<close> and \<open>\<Gamma>\<close> separate: theories can be liberal about supporting type |
|
20 |
constructors and schematic polymorphism of constants and axioms, while the |
|
21 |
inner calculus of \<open>\<Gamma> \<turnstile> \<phi>\<close> is strictly limited to Simple Type Theory (with |
|
20451 | 22 |
fixed type variables in the assumptions). |
18537 | 23 |
|
61416 | 24 |
\<^medskip> |
61854 | 25 |
Contexts and derivations are linked by the following key principles: |
20429 | 26 |
|
61854 | 27 |
\<^item> Transfer: monotonicity of derivations admits results to be transferred |
28 |
into a \<^emph>\<open>larger\<close> context, i.e.\ \<open>\<Gamma> \<turnstile>\<^sub>\<Theta> \<phi>\<close> implies \<open>\<Gamma>' \<turnstile>\<^sub>\<Theta>\<^sub>' \<phi>\<close> for contexts |
|
29 |
\<open>\<Theta>' \<supseteq> \<Theta>\<close> and \<open>\<Gamma>' \<supseteq> \<Gamma>\<close>. |
|
18537 | 30 |
|
61854 | 31 |
\<^item> Export: discharge of hypotheses admits results to be exported into a |
32 |
\<^emph>\<open>smaller\<close> context, i.e.\ \<open>\<Gamma>' \<turnstile>\<^sub>\<Theta> \<phi>\<close> implies \<open>\<Gamma> \<turnstile>\<^sub>\<Theta> \<Delta> \<Longrightarrow> \<phi>\<close> where \<open>\<Gamma>' \<supseteq> \<Gamma>\<close> |
|
33 |
and \<open>\<Delta> = \<Gamma>' - \<Gamma>\<close>. Note that \<open>\<Theta>\<close> remains unchanged here, only the \<open>\<Gamma>\<close> part is |
|
34 |
affected. |
|
20429 | 35 |
|
18537 | 36 |
|
61416 | 37 |
\<^medskip> |
61854 | 38 |
By modeling the main characteristics of the primitive \<open>\<Theta>\<close> and \<open>\<Gamma>\<close> above, and |
39 |
abstracting over any particular logical content, we arrive at the |
|
40 |
fundamental notions of \<^emph>\<open>theory context\<close> and \<^emph>\<open>proof context\<close> in |
|
41 |
Isabelle/Isar. These implement a certain policy to manage arbitrary |
|
42 |
\<^emph>\<open>context data\<close>. There is a strongly-typed mechanism to declare new kinds of |
|
20429 | 43 |
data at compile time. |
18537 | 44 |
|
61854 | 45 |
The internal bootstrap process of Isabelle/Pure eventually reaches a stage |
46 |
where certain data slots provide the logical content of \<open>\<Theta>\<close> and \<open>\<Gamma>\<close> sketched |
|
47 |
above, but this does not stop there! Various additional data slots support |
|
48 |
all kinds of mechanisms that are not necessarily part of the core logic. |
|
18537 | 49 |
|
61854 | 50 |
For example, there would be data for canonical introduction and elimination |
51 |
rules for arbitrary operators (depending on the object-logic and |
|
52 |
application), which enables users to perform standard proof steps implicitly |
|
53 |
(cf.\ the \<open>rule\<close> method @{cite "isabelle-isar-ref"}). |
|
18537 | 54 |
|
61416 | 55 |
\<^medskip> |
61854 | 56 |
Thus Isabelle/Isar is able to bring forth more and more concepts |
57 |
successively. In particular, an object-logic like Isabelle/HOL continues the |
|
58 |
Isabelle/Pure setup by adding specific components for automated reasoning |
|
59 |
(classical reasoner, tableau prover, structured induction etc.) and derived |
|
60 |
specification mechanisms (inductive predicates, recursive functions etc.). |
|
61 |
All of this is ultimately based on the generic data management by theory and |
|
62 |
proof contexts introduced here. |
|
58618 | 63 |
\<close> |
18537 | 64 |
|
65 |
||
58618 | 66 |
subsection \<open>Theory context \label{sec:context-theory}\<close> |
18537 | 67 |
|
61854 | 68 |
text \<open> |
69 |
A \<^emph>\<open>theory\<close> is a data container with explicit name and unique identifier. |
|
70 |
Theories are related by a (nominal) sub-theory relation, which corresponds |
|
71 |
to the dependency graph of the original construction; each theory is derived |
|
72 |
from a certain sub-graph of ancestor theories. To this end, the system |
|
73 |
maintains a set of symbolic ``identification stamps'' within each theory. |
|
18537 | 74 |
|
61854 | 75 |
The \<open>begin\<close> operation starts a new theory by importing several parent |
76 |
theories (with merged contents) and entering a special mode of nameless |
|
77 |
incremental updates, until the final \<open>end\<close> operation is performed. |
|
34921 | 78 |
|
61416 | 79 |
\<^medskip> |
61854 | 80 |
The example in \figref{fig:ex-theory} below shows a theory graph derived |
81 |
from \<open>Pure\<close>, with theory \<open>Length\<close> importing \<open>Nat\<close> and \<open>List\<close>. The body of |
|
82 |
\<open>Length\<close> consists of a sequence of updates, resulting in locally a linear |
|
83 |
sub-theory relation for each intermediate step. |
|
20447 | 84 |
|
85 |
\begin{figure}[htb] |
|
86 |
\begin{center} |
|
20429 | 87 |
\begin{tabular}{rcccl} |
61493 | 88 |
& & \<open>Pure\<close> \\ |
89 |
& & \<open>\<down>\<close> \\ |
|
90 |
& & \<open>FOL\<close> \\ |
|
18537 | 91 |
& $\swarrow$ & & $\searrow$ & \\ |
61493 | 92 |
\<open>Nat\<close> & & & & \<open>List\<close> \\ |
18537 | 93 |
& $\searrow$ & & $\swarrow$ \\ |
61493 | 94 |
& & \<open>Length\<close> \\ |
26864 | 95 |
& & \multicolumn{3}{l}{~~@{keyword "begin"}} \\ |
18537 | 96 |
& & $\vdots$~~ \\ |
26864 | 97 |
& & \multicolumn{3}{l}{~~@{command "end"}} \\ |
20429 | 98 |
\end{tabular} |
20451 | 99 |
\caption{A theory definition depending on ancestors}\label{fig:ex-theory} |
20447 | 100 |
\end{center} |
101 |
\end{figure} |
|
20451 | 102 |
|
61416 | 103 |
\<^medskip> |
61854 | 104 |
Derived formal entities may retain a reference to the background theory in |
105 |
order to indicate the formal context from which they were produced. This |
|
106 |
provides an immutable certificate of the background theory. |
|
107 |
\<close> |
|
18537 | 108 |
|
58618 | 109 |
text %mlref \<open> |
20447 | 110 |
\begin{mldecls} |
111 |
@{index_ML_type theory} \\ |
|
60948 | 112 |
@{index_ML Context.eq_thy: "theory * theory -> bool"} \\ |
113 |
@{index_ML Context.subthy: "theory * theory -> bool"} \\ |
|
48930 | 114 |
@{index_ML Theory.begin_theory: "string * Position.T -> theory list -> theory"} \\ |
39837 | 115 |
@{index_ML Theory.parents_of: "theory -> theory list"} \\ |
116 |
@{index_ML Theory.ancestors_of: "theory -> theory list"} \\ |
|
20547 | 117 |
\end{mldecls} |
20447 | 118 |
|
69597 | 119 |
\<^descr> Type \<^ML_type>\<open>theory\<close> represents theory contexts. |
20447 | 120 |
|
69597 | 121 |
\<^descr> \<^ML>\<open>Context.eq_thy\<close>~\<open>(thy\<^sub>1, thy\<^sub>2)\<close> check strict identity of two |
61854 | 122 |
theories. |
39837 | 123 |
|
69597 | 124 |
\<^descr> \<^ML>\<open>Context.subthy\<close>~\<open>(thy\<^sub>1, thy\<^sub>2)\<close> compares theories according to the |
61854 | 125 |
intrinsic graph structure of the construction. This sub-theory relation is a |
126 |
nominal approximation of inclusion (\<open>\<subseteq>\<close>) of the corresponding content |
|
127 |
(according to the semantics of the ML modules that implement the data). |
|
20447 | 128 |
|
69597 | 129 |
\<^descr> \<^ML>\<open>Theory.begin_theory\<close>~\<open>name parents\<close> constructs a new theory based |
61854 | 130 |
on the given parents. This ML function is normally not invoked directly. |
20447 | 131 |
|
69597 | 132 |
\<^descr> \<^ML>\<open>Theory.parents_of\<close>~\<open>thy\<close> returns the direct ancestors of \<open>thy\<close>. |
39837 | 133 |
|
69597 | 134 |
\<^descr> \<^ML>\<open>Theory.ancestors_of\<close>~\<open>thy\<close> returns all ancestors of \<open>thy\<close> (not |
61854 | 135 |
including \<open>thy\<close> itself). |
58618 | 136 |
\<close> |
20430 | 137 |
|
58618 | 138 |
text %mlantiq \<open> |
39832 | 139 |
\begin{matharray}{rcl} |
61493 | 140 |
@{ML_antiquotation_def "theory"} & : & \<open>ML_antiquotation\<close> \\ |
141 |
@{ML_antiquotation_def "theory_context"} & : & \<open>ML_antiquotation\<close> \\ |
|
39832 | 142 |
\end{matharray} |
143 |
||
69597 | 144 |
\<^rail>\<open> |
67146 | 145 |
@@{ML_antiquotation theory} embedded? |
51686 | 146 |
; |
67146 | 147 |
@@{ML_antiquotation theory_context} embedded |
69597 | 148 |
\<close> |
39832 | 149 |
|
61854 | 150 |
\<^descr> \<open>@{theory}\<close> refers to the background theory of the current context --- as |
151 |
abstract value. |
|
39832 | 152 |
|
61854 | 153 |
\<^descr> \<open>@{theory A}\<close> refers to an explicitly named ancestor theory \<open>A\<close> of the |
154 |
background theory of the current context --- as abstract value. |
|
39832 | 155 |
|
61854 | 156 |
\<^descr> \<open>@{theory_context A}\<close> is similar to \<open>@{theory A}\<close>, but presents the result |
69597 | 157 |
as initial \<^ML_type>\<open>Proof.context\<close> (see also \<^ML>\<open>Proof_Context.init_global\<close>). |
58618 | 158 |
\<close> |
39832 | 159 |
|
18537 | 160 |
|
58618 | 161 |
subsection \<open>Proof context \label{sec:context-proof}\<close> |
18537 | 162 |
|
61854 | 163 |
text \<open> |
164 |
A proof context is a container for pure data that refers to the theory from |
|
165 |
which it is derived. The \<open>init\<close> operation creates a proof context from a |
|
166 |
given theory. There is an explicit \<open>transfer\<close> operation to force |
|
167 |
resynchronization with updates to the background theory -- this is rarely |
|
168 |
required in practice. |
|
20429 | 169 |
|
61854 | 170 |
Entities derived in a proof context need to record logical requirements |
171 |
explicitly, since there is no separate context identification or symbolic |
|
172 |
inclusion as for theories. For example, hypotheses used in primitive |
|
173 |
derivations (cf.\ \secref{sec:thms}) are recorded separately within the |
|
174 |
sequent \<open>\<Gamma> \<turnstile> \<phi>\<close>, just to make double sure. Results could still leak into an |
|
175 |
alien proof context due to programming errors, but Isabelle/Isar includes |
|
176 |
some extra validity checks in critical positions, notably at the end of a |
|
34921 | 177 |
sub-proof. |
20429 | 178 |
|
20451 | 179 |
Proof contexts may be manipulated arbitrarily, although the common |
61854 | 180 |
discipline is to follow block structure as a mental model: a given context |
181 |
is extended consecutively, and results are exported back into the original |
|
182 |
context. Note that an Isar proof state models block-structured reasoning |
|
183 |
explicitly, using a stack of proof contexts internally. For various |
|
184 |
technical reasons, the background theory of an Isar proof state must not be |
|
185 |
changed while the proof is still under construction! |
|
58618 | 186 |
\<close> |
18537 | 187 |
|
58618 | 188 |
text %mlref \<open> |
20449 | 189 |
\begin{mldecls} |
190 |
@{index_ML_type Proof.context} \\ |
|
42361 | 191 |
@{index_ML Proof_Context.init_global: "theory -> Proof.context"} \\ |
192 |
@{index_ML Proof_Context.theory_of: "Proof.context -> theory"} \\ |
|
193 |
@{index_ML Proof_Context.transfer: "theory -> Proof.context -> Proof.context"} \\ |
|
20449 | 194 |
\end{mldecls} |
195 |
||
69597 | 196 |
\<^descr> Type \<^ML_type>\<open>Proof.context\<close> represents proof contexts. |
20449 | 197 |
|
69597 | 198 |
\<^descr> \<^ML>\<open>Proof_Context.init_global\<close>~\<open>thy\<close> produces a proof context derived |
61854 | 199 |
from \<open>thy\<close>, initializing all data. |
20449 | 200 |
|
69597 | 201 |
\<^descr> \<^ML>\<open>Proof_Context.theory_of\<close>~\<open>ctxt\<close> selects the background theory from |
61854 | 202 |
\<open>ctxt\<close>. |
20449 | 203 |
|
69597 | 204 |
\<^descr> \<^ML>\<open>Proof_Context.transfer\<close>~\<open>thy ctxt\<close> promotes the background theory of |
61854 | 205 |
\<open>ctxt\<close> to the super theory \<open>thy\<close>. |
58618 | 206 |
\<close> |
20449 | 207 |
|
58618 | 208 |
text %mlantiq \<open> |
39832 | 209 |
\begin{matharray}{rcl} |
61493 | 210 |
@{ML_antiquotation_def "context"} & : & \<open>ML_antiquotation\<close> \\ |
39832 | 211 |
\end{matharray} |
212 |
||
61854 | 213 |
\<^descr> \<open>@{context}\<close> refers to \<^emph>\<open>the\<close> context at compile-time --- as abstract |
214 |
value. Independently of (local) theory or proof mode, this always produces a |
|
215 |
meaningful result. |
|
39832 | 216 |
|
217 |
This is probably the most common antiquotation in interactive |
|
218 |
experimentation with ML inside Isar. |
|
58618 | 219 |
\<close> |
39832 | 220 |
|
20430 | 221 |
|
58618 | 222 |
subsection \<open>Generic contexts \label{sec:generic-context}\<close> |
20429 | 223 |
|
58618 | 224 |
text \<open> |
61854 | 225 |
A generic context is the disjoint sum of either a theory or proof context. |
226 |
Occasionally, this enables uniform treatment of generic context data, |
|
227 |
typically extra-logical information. Operations on generic contexts include |
|
228 |
the usual injections, partial selections, and combinators for lifting |
|
229 |
operations on either component of the disjoint sum. |
|
20449 | 230 |
|
61854 | 231 |
Moreover, there are total operations \<open>theory_of\<close> and \<open>proof_of\<close> to convert a |
232 |
generic context into either kind: a theory can always be selected from the |
|
233 |
sum, while a proof context might have to be constructed by an ad-hoc \<open>init\<close> |
|
234 |
operation, which incurs a small runtime overhead. |
|
58618 | 235 |
\<close> |
20430 | 236 |
|
58618 | 237 |
text %mlref \<open> |
20449 | 238 |
\begin{mldecls} |
239 |
@{index_ML_type Context.generic} \\ |
|
240 |
@{index_ML Context.theory_of: "Context.generic -> theory"} \\ |
|
241 |
@{index_ML Context.proof_of: "Context.generic -> Proof.context"} \\ |
|
242 |
\end{mldecls} |
|
243 |
||
69597 | 244 |
\<^descr> Type \<^ML_type>\<open>Context.generic\<close> is the direct sum of \<^ML_type>\<open>theory\<close> |
245 |
and \<^ML_type>\<open>Proof.context\<close>, with the datatype constructors \<^ML>\<open>Context.Theory\<close> and \<^ML>\<open>Context.Proof\<close>. |
|
20449 | 246 |
|
69597 | 247 |
\<^descr> \<^ML>\<open>Context.theory_of\<close>~\<open>context\<close> always produces a theory from the |
248 |
generic \<open>context\<close>, using \<^ML>\<open>Proof_Context.theory_of\<close> as required. |
|
20449 | 249 |
|
69597 | 250 |
\<^descr> \<^ML>\<open>Context.proof_of\<close>~\<open>context\<close> always produces a proof context from the |
251 |
generic \<open>context\<close>, using \<^ML>\<open>Proof_Context.init_global\<close> as required (note |
|
61854 | 252 |
that this re-initializes the context data with each invocation). |
58618 | 253 |
\<close> |
20437 | 254 |
|
20476 | 255 |
|
58618 | 256 |
subsection \<open>Context data \label{sec:context-data}\<close> |
20447 | 257 |
|
61854 | 258 |
text \<open> |
259 |
The main purpose of theory and proof contexts is to manage arbitrary (pure) |
|
260 |
data. New data types can be declared incrementally at compile time. There |
|
261 |
are separate declaration mechanisms for any of the three kinds of contexts: |
|
262 |
theory, proof, generic. |
|
263 |
\<close> |
|
20449 | 264 |
|
61506 | 265 |
paragraph \<open>Theory data\<close> |
266 |
text \<open>declarations need to implement the following ML signature: |
|
20449 | 267 |
|
61416 | 268 |
\<^medskip> |
20449 | 269 |
\begin{tabular}{ll} |
61493 | 270 |
\<open>\<type> T\<close> & representing type \\ |
271 |
\<open>\<val> empty: T\<close> & empty default value \\ |
|
272 |
\<open>\<val> extend: T \<rightarrow> T\<close> & re-initialize on import \\ |
|
273 |
\<open>\<val> merge: T \<times> T \<rightarrow> T\<close> & join on import \\ |
|
20449 | 274 |
\end{tabular} |
61416 | 275 |
\<^medskip> |
20449 | 276 |
|
61854 | 277 |
The \<open>empty\<close> value acts as initial default for \<^emph>\<open>any\<close> theory that does not |
69292 | 278 |
declare actual data content; \<open>extend\<close> acts like a unitary version of |
61854 | 279 |
\<open>merge\<close>. |
20449 | 280 |
|
61854 | 281 |
Implementing \<open>merge\<close> can be tricky. The general idea is that \<open>merge (data\<^sub>1, |
282 |
data\<^sub>2)\<close> inserts those parts of \<open>data\<^sub>2\<close> into \<open>data\<^sub>1\<close> that are not yet |
|
69597 | 283 |
present, while keeping the general order of things. The \<^ML>\<open>Library.merge\<close> |
34921 | 284 |
function on plain lists may serve as canonical template. |
285 |
||
61854 | 286 |
Particularly note that shared parts of the data must not be duplicated by |
287 |
naive concatenation, or a theory graph that is like a chain of diamonds |
|
288 |
would cause an exponential blowup! |
|
61506 | 289 |
\<close> |
34921 | 290 |
|
61506 | 291 |
paragraph \<open>Proof context data\<close> |
292 |
text \<open>declarations need to implement the following ML signature: |
|
20449 | 293 |
|
61416 | 294 |
\<^medskip> |
20449 | 295 |
\begin{tabular}{ll} |
61493 | 296 |
\<open>\<type> T\<close> & representing type \\ |
297 |
\<open>\<val> init: theory \<rightarrow> T\<close> & produce initial value \\ |
|
20449 | 298 |
\end{tabular} |
61416 | 299 |
\<^medskip> |
20449 | 300 |
|
61854 | 301 |
The \<open>init\<close> operation is supposed to produce a pure value from the given |
302 |
background theory and should be somehow ``immediate''. Whenever a proof |
|
303 |
context is initialized, which happens frequently, the the system invokes the |
|
304 |
\<open>init\<close> operation of \<^emph>\<open>all\<close> theory data slots ever declared. This also means |
|
305 |
that one needs to be economic about the total number of proof data |
|
306 |
declarations in the system, i.e.\ each ML module should declare at most one, |
|
307 |
sometimes two data slots for its internal use. Repeated data declarations to |
|
308 |
simulate a record type should be avoided! |
|
61506 | 309 |
\<close> |
20449 | 310 |
|
61506 | 311 |
paragraph \<open>Generic data\<close> |
61854 | 312 |
text \<open> |
313 |
provides a hybrid interface for both theory and proof data. The \<open>init\<close> |
|
314 |
operation for proof contexts is predefined to select the current data value |
|
315 |
from the background theory. |
|
20449 | 316 |
|
61416 | 317 |
\<^bigskip> |
61854 | 318 |
Any of the above data declarations over type \<open>T\<close> result in an ML structure |
319 |
with the following signature: |
|
20449 | 320 |
|
61416 | 321 |
\<^medskip> |
20449 | 322 |
\begin{tabular}{ll} |
61493 | 323 |
\<open>get: context \<rightarrow> T\<close> \\ |
324 |
\<open>put: T \<rightarrow> context \<rightarrow> context\<close> \\ |
|
325 |
\<open>map: (T \<rightarrow> T) \<rightarrow> context \<rightarrow> context\<close> \\ |
|
20449 | 326 |
\end{tabular} |
61416 | 327 |
\<^medskip> |
20449 | 328 |
|
61854 | 329 |
These other operations provide exclusive access for the particular kind of |
330 |
context (theory, proof, or generic context). This interface observes the ML |
|
331 |
discipline for types and scopes: there is no other way to access the |
|
332 |
corresponding data slot of a context. By keeping these operations private, |
|
333 |
an Isabelle/ML module may maintain abstract values authentically. |
|
334 |
\<close> |
|
20447 | 335 |
|
58618 | 336 |
text %mlref \<open> |
20450 | 337 |
\begin{mldecls} |
33524
a08e6c1cbc04
updated functor Theory_Data, Proof_Data, Generic_Data;
wenzelm
parents:
33174
diff
changeset
|
338 |
@{index_ML_functor Theory_Data} \\ |
a08e6c1cbc04
updated functor Theory_Data, Proof_Data, Generic_Data;
wenzelm
parents:
33174
diff
changeset
|
339 |
@{index_ML_functor Proof_Data} \\ |
a08e6c1cbc04
updated functor Theory_Data, Proof_Data, Generic_Data;
wenzelm
parents:
33174
diff
changeset
|
340 |
@{index_ML_functor Generic_Data} \\ |
20450 | 341 |
\end{mldecls} |
342 |
||
69597 | 343 |
\<^descr> \<^ML_functor>\<open>Theory_Data\<close>\<open>(spec)\<close> declares data for type \<^ML_type>\<open>theory\<close> |
61854 | 344 |
according to the specification provided as argument structure. The resulting |
345 |
structure provides data init and access operations as described above. |
|
20450 | 346 |
|
69597 | 347 |
\<^descr> \<^ML_functor>\<open>Proof_Data\<close>\<open>(spec)\<close> is analogous to \<^ML_functor>\<open>Theory_Data\<close> |
348 |
for type \<^ML_type>\<open>Proof.context\<close>. |
|
20450 | 349 |
|
69597 | 350 |
\<^descr> \<^ML_functor>\<open>Generic_Data\<close>\<open>(spec)\<close> is analogous to \<^ML_functor>\<open>Theory_Data\<close> for type \<^ML_type>\<open>Context.generic\<close>. \<close> |
20450 | 351 |
|
58618 | 352 |
text %mlex \<open> |
61854 | 353 |
The following artificial example demonstrates theory data: we maintain a set |
354 |
of terms that are supposed to be wellformed wrt.\ the enclosing theory. The |
|
355 |
public interface is as follows: |
|
58618 | 356 |
\<close> |
34928 | 357 |
|
58618 | 358 |
ML \<open> |
34928 | 359 |
signature WELLFORMED_TERMS = |
360 |
sig |
|
361 |
val get: theory -> term list |
|
362 |
val add: term -> theory -> theory |
|
363 |
end; |
|
58618 | 364 |
\<close> |
34928 | 365 |
|
61854 | 366 |
text \<open> |
367 |
The implementation uses private theory data internally, and only exposes an |
|
368 |
operation that involves explicit argument checking wrt.\ the given theory. |
|
369 |
\<close> |
|
34928 | 370 |
|
58618 | 371 |
ML \<open> |
34928 | 372 |
structure Wellformed_Terms: WELLFORMED_TERMS = |
373 |
struct |
|
374 |
||
375 |
structure Terms = Theory_Data |
|
376 |
( |
|
39687 | 377 |
type T = term Ord_List.T; |
34928 | 378 |
val empty = []; |
379 |
val extend = I; |
|
380 |
fun merge (ts1, ts2) = |
|
39687 | 381 |
Ord_List.union Term_Ord.fast_term_ord ts1 ts2; |
39861
b8d89db3e238
use continental paragraph style, which works better with mixture of (in)formal text;
wenzelm
parents:
39857
diff
changeset
|
382 |
); |
34928 | 383 |
|
384 |
val get = Terms.get; |
|
385 |
||
386 |
fun add raw_t thy = |
|
39821 | 387 |
let |
388 |
val t = Sign.cert_term thy raw_t; |
|
389 |
in |
|
390 |
Terms.map (Ord_List.insert Term_Ord.fast_term_ord t) thy |
|
391 |
end; |
|
34928 | 392 |
|
393 |
end; |
|
58618 | 394 |
\<close> |
34928 | 395 |
|
61854 | 396 |
text \<open> |
69597 | 397 |
Type \<^ML_type>\<open>term Ord_List.T\<close> is used for reasonably efficient |
61854 | 398 |
representation of a set of terms: all operations are linear in the number of |
399 |
stored elements. Here we assume that users of this module do not care about |
|
400 |
the declaration order, since that data structure forces its own arrangement |
|
401 |
of elements. |
|
34928 | 402 |
|
69597 | 403 |
Observe how the \<^ML_text>\<open>merge\<close> operation joins the data slots of the two |
404 |
constituents: \<^ML>\<open>Ord_List.union\<close> prevents duplication of common data from |
|
61854 | 405 |
different branches, thus avoiding the danger of exponential blowup. Plain |
406 |
list append etc.\ must never be used for theory data merges! |
|
34928 | 407 |
|
61416 | 408 |
\<^medskip> |
409 |
Our intended invariant is achieved as follows: |
|
34928 | 410 |
|
69597 | 411 |
\<^enum> \<^ML>\<open>Wellformed_Terms.add\<close> only admits terms that have passed the \<^ML>\<open>Sign.cert_term\<close> check of the given theory at that point. |
61854 | 412 |
|
69597 | 413 |
\<^enum> Wellformedness in the sense of \<^ML>\<open>Sign.cert_term\<close> is monotonic wrt.\ |
61854 | 414 |
the sub-theory relation. So our data can move upwards in the hierarchy |
415 |
(via extension or merges), and maintain wellformedness without further |
|
416 |
checks. |
|
34928 | 417 |
|
69597 | 418 |
Note that all basic operations of the inference kernel (which includes \<^ML>\<open>Sign.cert_term\<close>) observe this monotonicity principle, but other user-space |
419 |
tools don't. For example, fully-featured type-inference via \<^ML>\<open>Syntax.check_term\<close> (cf.\ \secref{sec:term-check}) is not necessarily |
|
61854 | 420 |
monotonic wrt.\ the background theory, since constraints of term constants |
421 |
can be modified by later declarations, for example. |
|
34928 | 422 |
|
61854 | 423 |
In most cases, user-space context data does not have to take such invariants |
424 |
too seriously. The situation is different in the implementation of the |
|
425 |
inference kernel itself, which uses the very same data mechanisms for types, |
|
426 |
constants, axioms etc. |
|
58618 | 427 |
\<close> |
34928 | 428 |
|
20447 | 429 |
|
58618 | 430 |
subsection \<open>Configuration options \label{sec:config-options}\<close> |
39865 | 431 |
|
61854 | 432 |
text \<open> |
433 |
A \<^emph>\<open>configuration option\<close> is a named optional value of some basic type |
|
434 |
(Boolean, integer, string) that is stored in the context. It is a simple |
|
435 |
application of general context data (\secref{sec:context-data}) that is |
|
436 |
sufficiently common to justify customized setup, which includes some |
|
437 |
concrete declarations for end-users using existing notation for attributes |
|
438 |
(cf.\ \secref{sec:attributes}). |
|
39865 | 439 |
|
61854 | 440 |
For example, the predefined configuration option @{attribute show_types} |
441 |
controls output of explicit type constraints for variables in printed terms |
|
442 |
(cf.\ \secref{sec:read-print}). Its value can be modified within Isar text |
|
443 |
like this: |
|
58618 | 444 |
\<close> |
39865 | 445 |
|
59902 | 446 |
experiment |
447 |
begin |
|
448 |
||
39865 | 449 |
declare [[show_types = false]] |
61580 | 450 |
\<comment> \<open>declaration within (local) theory context\<close> |
39865 | 451 |
|
40964 | 452 |
notepad |
453 |
begin |
|
39865 | 454 |
note [[show_types = true]] |
61580 | 455 |
\<comment> \<open>declaration within proof (forward mode)\<close> |
39865 | 456 |
term x |
457 |
||
458 |
have "x = x" |
|
459 |
using [[show_types = false]] |
|
61580 | 460 |
\<comment> \<open>declaration within proof (backward mode)\<close> |
39865 | 461 |
.. |
40964 | 462 |
end |
39865 | 463 |
|
59902 | 464 |
end |
465 |
||
61854 | 466 |
text \<open> |
467 |
Configuration options that are not set explicitly hold a default value that |
|
468 |
can depend on the application context. This allows to retrieve the value |
|
469 |
from another slot within the context, or fall back on a global preference |
|
470 |
mechanism, for example. |
|
39865 | 471 |
|
61854 | 472 |
The operations to declare configuration options and get/map their values are |
473 |
modeled as direct replacements for historic global references, only that the |
|
474 |
context is made explicit. This allows easy configuration of tools, without |
|
475 |
relying on the execution order as required for old-style mutable |
|
476 |
references. |
|
477 |
\<close> |
|
39865 | 478 |
|
58618 | 479 |
text %mlref \<open> |
39865 | 480 |
\begin{mldecls} |
481 |
@{index_ML Config.get: "Proof.context -> 'a Config.T -> 'a"} \\ |
|
482 |
@{index_ML Config.map: "'a Config.T -> ('a -> 'a) -> Proof.context -> Proof.context"} \\ |
|
42616
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
483 |
@{index_ML Attrib.setup_config_bool: "binding -> (Context.generic -> bool) -> |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
484 |
bool Config.T"} \\ |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
485 |
@{index_ML Attrib.setup_config_int: "binding -> (Context.generic -> int) -> |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
486 |
int Config.T"} \\ |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
487 |
@{index_ML Attrib.setup_config_real: "binding -> (Context.generic -> real) -> |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
488 |
real Config.T"} \\ |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
489 |
@{index_ML Attrib.setup_config_string: "binding -> (Context.generic -> string) -> |
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
490 |
string Config.T"} \\ |
39865 | 491 |
\end{mldecls} |
492 |
||
69597 | 493 |
\<^descr> \<^ML>\<open>Config.get\<close>~\<open>ctxt config\<close> gets the value of \<open>config\<close> in the given |
61854 | 494 |
context. |
39865 | 495 |
|
69597 | 496 |
\<^descr> \<^ML>\<open>Config.map\<close>~\<open>config f ctxt\<close> updates the context by updating the value |
61854 | 497 |
of \<open>config\<close>. |
39865 | 498 |
|
69597 | 499 |
\<^descr> \<open>config =\<close>~\<^ML>\<open>Attrib.setup_config_bool\<close>~\<open>name default\<close> creates a named |
500 |
configuration option of type \<^ML_type>\<open>bool\<close>, with the given \<open>default\<close> |
|
61854 | 501 |
depending on the application context. The resulting \<open>config\<close> can be used to |
502 |
get/map its value in a given context. There is an implicit update of the |
|
503 |
background theory that registers the option as attribute with some concrete |
|
504 |
syntax. |
|
39865 | 505 |
|
69597 | 506 |
\<^descr> \<^ML>\<open>Attrib.config_int\<close>, \<^ML>\<open>Attrib.config_real\<close>, and \<^ML>\<open>Attrib.config_string\<close> work like \<^ML>\<open>Attrib.config_bool\<close>, but for types |
507 |
\<^ML_type>\<open>int\<close> and \<^ML_type>\<open>string\<close>, respectively. |
|
58618 | 508 |
\<close> |
39865 | 509 |
|
61854 | 510 |
text %mlex \<open> |
511 |
The following example shows how to declare and use a Boolean configuration |
|
69597 | 512 |
option called \<open>my_flag\<close> with constant default value \<^ML>\<open>false\<close>. |
61854 | 513 |
\<close> |
39865 | 514 |
|
58618 | 515 |
ML \<open> |
42616
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
516 |
val my_flag = |
69597 | 517 |
Attrib.setup_config_bool \<^binding>\<open>my_flag\<close> (K false) |
58618 | 518 |
\<close> |
39865 | 519 |
|
61854 | 520 |
text \<open> |
521 |
Now the user can refer to @{attribute my_flag} in declarations, while ML |
|
69597 | 522 |
tools can retrieve the current value from the context via \<^ML>\<open>Config.get\<close>. |
61854 | 523 |
\<close> |
39865 | 524 |
|
69597 | 525 |
ML_val \<open>\<^assert> (Config.get \<^context> my_flag = false)\<close> |
39865 | 526 |
|
527 |
declare [[my_flag = true]] |
|
528 |
||
69597 | 529 |
ML_val \<open>\<^assert> (Config.get \<^context> my_flag = true)\<close> |
39865 | 530 |
|
40964 | 531 |
notepad |
532 |
begin |
|
39866
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
533 |
{ |
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
534 |
note [[my_flag = false]] |
69597 | 535 |
ML_val \<open>\<^assert> (Config.get \<^context> my_flag = false)\<close> |
39866
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
536 |
} |
69597 | 537 |
ML_val \<open>\<^assert> (Config.get \<^context> my_flag = true)\<close> |
40964 | 538 |
end |
39865 | 539 |
|
61854 | 540 |
text \<open> |
69597 | 541 |
Here is another example involving ML type \<^ML_type>\<open>real\<close> (floating-point |
61854 | 542 |
numbers). |
543 |
\<close> |
|
40291 | 544 |
|
58618 | 545 |
ML \<open> |
42616
92715b528e78
added Attrib.setup_config_XXX conveniences, with implicit setup of the background theory;
wenzelm
parents:
42510
diff
changeset
|
546 |
val airspeed_velocity = |
69597 | 547 |
Attrib.setup_config_real \<^binding>\<open>airspeed_velocity\<close> (K 0.0) |
58618 | 548 |
\<close> |
40291 | 549 |
|
40296 | 550 |
declare [[airspeed_velocity = 10]] |
40291 | 551 |
declare [[airspeed_velocity = 9.9]] |
552 |
||
39865 | 553 |
|
58618 | 554 |
section \<open>Names \label{sec:names}\<close> |
20451 | 555 |
|
61854 | 556 |
text \<open> |
557 |
In principle, a name is just a string, but there are various conventions for |
|
558 |
representing additional structure. For example, ``\<open>Foo.bar.baz\<close>'' is |
|
559 |
considered as a long name consisting of qualifier \<open>Foo.bar\<close> and base name |
|
560 |
\<open>baz\<close>. The individual constituents of a name may have further substructure, |
|
561 |
e.g.\ the string ``\<^verbatim>\<open>\<alpha>\<close>'' encodes as a single symbol (\secref{sec:symbols}). |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
562 |
|
61416 | 563 |
\<^medskip> |
61854 | 564 |
Subsequently, we shall introduce specific categories of names. Roughly |
565 |
speaking these correspond to logical entities as follows: |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
566 |
|
61854 | 567 |
\<^item> Basic names (\secref{sec:basic-name}): free and bound variables. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
568 |
|
61416 | 569 |
\<^item> Indexed names (\secref{sec:indexname}): schematic variables. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
570 |
|
61854 | 571 |
\<^item> Long names (\secref{sec:long-name}): constants of any kind (type |
572 |
constructors, term constants, other concepts defined in user space). Such |
|
573 |
entities are typically managed via name spaces (\secref{sec:name-space}). |
|
58618 | 574 |
\<close> |
20437 | 575 |
|
576 |
||
58618 | 577 |
subsection \<open>Basic names \label{sec:basic-name}\<close> |
20476 | 578 |
|
58618 | 579 |
text \<open> |
61854 | 580 |
A \<^emph>\<open>basic name\<close> essentially consists of a single Isabelle identifier. There |
581 |
are conventions to mark separate classes of basic names, by attaching a |
|
582 |
suffix of underscores: one underscore means \<^emph>\<open>internal name\<close>, two |
|
583 |
underscores means \<^emph>\<open>Skolem name\<close>, three underscores means \<^emph>\<open>internal Skolem |
|
584 |
name\<close>. |
|
20476 | 585 |
|
61854 | 586 |
For example, the basic name \<open>foo\<close> has the internal version \<open>foo_\<close>, with |
587 |
Skolem versions \<open>foo__\<close> and \<open>foo___\<close>, respectively. |
|
20476 | 588 |
|
61854 | 589 |
These special versions provide copies of the basic name space, apart from |
590 |
anything that normally appears in the user text. For example, system |
|
591 |
generated variables in Isar proof contexts are usually marked as internal, |
|
592 |
which prevents mysterious names like \<open>xaa\<close> to appear in human-readable text. |
|
20476 | 593 |
|
61416 | 594 |
\<^medskip> |
61854 | 595 |
Manipulating binding scopes often requires on-the-fly renamings. A \<^emph>\<open>name |
596 |
context\<close> contains a collection of already used names. The \<open>declare\<close> |
|
597 |
operation adds names to the context. |
|
20476 | 598 |
|
61854 | 599 |
The \<open>invents\<close> operation derives a number of fresh names from a given |
600 |
starting point. For example, the first three names derived from \<open>a\<close> are \<open>a\<close>, |
|
601 |
\<open>b\<close>, \<open>c\<close>. |
|
20476 | 602 |
|
61854 | 603 |
The \<open>variants\<close> operation produces fresh names by incrementing tentative |
604 |
names as base-26 numbers (with digits \<open>a..z\<close>) until all clashes are |
|
605 |
resolved. For example, name \<open>foo\<close> results in variants \<open>fooa\<close>, \<open>foob\<close>, |
|
606 |
\<open>fooc\<close>, \dots, \<open>fooaa\<close>, \<open>fooab\<close> etc.; each renaming step picks the next |
|
607 |
unused variant from this sequence. |
|
58618 | 608 |
\<close> |
20476 | 609 |
|
58618 | 610 |
text %mlref \<open> |
20476 | 611 |
\begin{mldecls} |
612 |
@{index_ML Name.internal: "string -> string"} \\ |
|
20547 | 613 |
@{index_ML Name.skolem: "string -> string"} \\ |
614 |
\end{mldecls} |
|
615 |
\begin{mldecls} |
|
20476 | 616 |
@{index_ML_type Name.context} \\ |
617 |
@{index_ML Name.context: Name.context} \\ |
|
618 |
@{index_ML Name.declare: "string -> Name.context -> Name.context"} \\ |
|
43329
84472e198515
tuned signature: Name.invent and Name.invent_names;
wenzelm
parents:
43326
diff
changeset
|
619 |
@{index_ML Name.invent: "Name.context -> string -> int -> string list"} \\ |
43326
47cf4bc789aa
simplified Name.variant -- discontinued builtin fold_map;
wenzelm
parents:
42616
diff
changeset
|
620 |
@{index_ML Name.variant: "string -> Name.context -> string * Name.context"} \\ |
20476 | 621 |
\end{mldecls} |
34926 | 622 |
\begin{mldecls} |
623 |
@{index_ML Variable.names_of: "Proof.context -> Name.context"} \\ |
|
624 |
\end{mldecls} |
|
20476 | 625 |
|
69597 | 626 |
\<^descr> \<^ML>\<open>Name.internal\<close>~\<open>name\<close> produces an internal name by adding one |
61854 | 627 |
underscore. |
20476 | 628 |
|
69597 | 629 |
\<^descr> \<^ML>\<open>Name.skolem\<close>~\<open>name\<close> produces a Skolem name by adding two underscores. |
20476 | 630 |
|
69597 | 631 |
\<^descr> Type \<^ML_type>\<open>Name.context\<close> represents the context of already used names; |
632 |
the initial value is \<^ML>\<open>Name.context\<close>. |
|
20476 | 633 |
|
69597 | 634 |
\<^descr> \<^ML>\<open>Name.declare\<close>~\<open>name\<close> enters a used name into the context. |
20437 | 635 |
|
69597 | 636 |
\<^descr> \<^ML>\<open>Name.invent\<close>~\<open>context name n\<close> produces \<open>n\<close> fresh names derived from |
61854 | 637 |
\<open>name\<close>. |
20488 | 638 |
|
69597 | 639 |
\<^descr> \<^ML>\<open>Name.variant\<close>~\<open>name context\<close> produces a fresh variant of \<open>name\<close>; the |
61854 | 640 |
result is declared to the context. |
20476 | 641 |
|
69597 | 642 |
\<^descr> \<^ML>\<open>Variable.names_of\<close>~\<open>ctxt\<close> retrieves the context of declared type and |
61854 | 643 |
term variable names. Projecting a proof context down to a primitive name |
644 |
context is occasionally useful when invoking lower-level operations. Regular |
|
645 |
management of ``fresh variables'' is done by suitable operations of |
|
69597 | 646 |
structure \<^ML_structure>\<open>Variable\<close>, which is also able to provide an |
61854 | 647 |
official status of ``locally fixed variable'' within the logical environment |
648 |
(cf.\ \secref{sec:variables}). |
|
58618 | 649 |
\<close> |
20476 | 650 |
|
61854 | 651 |
text %mlex \<open> |
652 |
The following simple examples demonstrate how to produce fresh names from |
|
69597 | 653 |
the initial \<^ML>\<open>Name.context\<close>. |
61854 | 654 |
\<close> |
39857 | 655 |
|
59902 | 656 |
ML_val \<open> |
43329
84472e198515
tuned signature: Name.invent and Name.invent_names;
wenzelm
parents:
43326
diff
changeset
|
657 |
val list1 = Name.invent Name.context "a" 5; |
69597 | 658 |
\<^assert> (list1 = ["a", "b", "c", "d", "e"]); |
39866
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
659 |
|
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
660 |
val list2 = |
43326
47cf4bc789aa
simplified Name.variant -- discontinued builtin fold_map;
wenzelm
parents:
42616
diff
changeset
|
661 |
#1 (fold_map Name.variant ["x", "x", "a", "a", "'a", "'a"] Name.context); |
69597 | 662 |
\<^assert> (list2 = ["x", "xa", "a", "aa", "'a", "'aa"]); |
58618 | 663 |
\<close> |
39857 | 664 |
|
61416 | 665 |
text \<open> |
666 |
\<^medskip> |
|
667 |
The same works relatively to the formal context as follows.\<close> |
|
39857 | 668 |
|
59902 | 669 |
experiment fixes a b c :: 'a |
39857 | 670 |
begin |
671 |
||
59902 | 672 |
ML_val \<open> |
69597 | 673 |
val names = Variable.names_of \<^context>; |
39866
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
674 |
|
43329
84472e198515
tuned signature: Name.invent and Name.invent_names;
wenzelm
parents:
43326
diff
changeset
|
675 |
val list1 = Name.invent names "a" 5; |
69597 | 676 |
\<^assert> (list1 = ["d", "e", "f", "g", "h"]); |
39866
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
677 |
|
5ec01d5acd0c
more robust examples: explicit @{assert} instead of unchecked output;
wenzelm
parents:
39865
diff
changeset
|
678 |
val list2 = |
43326
47cf4bc789aa
simplified Name.variant -- discontinued builtin fold_map;
wenzelm
parents:
42616
diff
changeset
|
679 |
#1 (fold_map Name.variant ["x", "x", "a", "a", "'a", "'a"] names); |
69597 | 680 |
\<^assert> (list2 = ["x", "xa", "aa", "ab", "'aa", "'ab"]); |
58618 | 681 |
\<close> |
39857 | 682 |
|
683 |
end |
|
684 |
||
20476 | 685 |
|
58618 | 686 |
subsection \<open>Indexed names \label{sec:indexname}\<close> |
20476 | 687 |
|
58618 | 688 |
text \<open> |
61854 | 689 |
An \<^emph>\<open>indexed name\<close> (or \<open>indexname\<close>) is a pair of a basic name and a natural |
690 |
number. This representation allows efficient renaming by incrementing the |
|
691 |
second component only. The canonical way to rename two collections of |
|
692 |
indexnames apart from each other is this: determine the maximum index |
|
693 |
\<open>maxidx\<close> of the first collection, then increment all indexes of the second |
|
694 |
collection by \<open>maxidx + 1\<close>; the maximum index of an empty collection is |
|
61493 | 695 |
\<open>-1\<close>. |
20476 | 696 |
|
61854 | 697 |
Occasionally, basic names are injected into the same pair type of indexed |
698 |
names: then \<open>(x, -1)\<close> is used to encode the basic name \<open>x\<close>. |
|
20488 | 699 |
|
61416 | 700 |
\<^medskip> |
61854 | 701 |
Isabelle syntax observes the following rules for representing an indexname |
702 |
\<open>(x, i)\<close> as a packed string: |
|
20476 | 703 |
|
61854 | 704 |
\<^item> \<open>?x\<close> if \<open>x\<close> does not end with a digit and \<open>i = 0\<close>, |
20476 | 705 |
|
61854 | 706 |
\<^item> \<open>?xi\<close> if \<open>x\<close> does not end with a digit, |
20476 | 707 |
|
61854 | 708 |
\<^item> \<open>?x.i\<close> otherwise. |
20470 | 709 |
|
61854 | 710 |
Indexnames may acquire large index numbers after several maxidx shifts have |
711 |
been applied. Results are usually normalized towards \<open>0\<close> at certain |
|
712 |
checkpoints, notably at the end of a proof. This works by producing variants |
|
713 |
of the corresponding basic name components. For example, the collection |
|
714 |
\<open>?x1, ?x7, ?x42\<close> becomes \<open>?x, ?xa, ?xb\<close>. |
|
58618 | 715 |
\<close> |
20476 | 716 |
|
58618 | 717 |
text %mlref \<open> |
20476 | 718 |
\begin{mldecls} |
39861
b8d89db3e238
use continental paragraph style, which works better with mixture of (in)formal text;
wenzelm
parents:
39857
diff
changeset
|
719 |
@{index_ML_type indexname: "string * int"} \\ |
20476 | 720 |
\end{mldecls} |
721 |
||
69597 | 722 |
\<^descr> Type \<^ML_type>\<open>indexname\<close> represents indexed names. This is an |
723 |
abbreviation for \<^ML_type>\<open>string * int\<close>. The second component is usually |
|
61854 | 724 |
non-negative, except for situations where \<open>(x, -1)\<close> is used to inject basic |
725 |
names into this type. Other negative indexes should not be used. |
|
58618 | 726 |
\<close> |
20476 | 727 |
|
728 |
||
58618 | 729 |
subsection \<open>Long names \label{sec:long-name}\<close> |
20476 | 730 |
|
61854 | 731 |
text \<open> |
732 |
A \<^emph>\<open>long name\<close> consists of a sequence of non-empty name components. The |
|
733 |
packed representation uses a dot as separator, as in ``\<open>A.b.c\<close>''. The last |
|
734 |
component is called \<^emph>\<open>base name\<close>, the remaining prefix is called |
|
735 |
\<^emph>\<open>qualifier\<close> (which may be empty). The qualifier can be understood as the |
|
736 |
access path to the named entity while passing through some nested |
|
737 |
block-structure, although our free-form long names do not really enforce any |
|
738 |
strict discipline. |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
739 |
|
61854 | 740 |
For example, an item named ``\<open>A.b.c\<close>'' may be understood as a local entity |
741 |
\<open>c\<close>, within a local structure \<open>b\<close>, within a global structure \<open>A\<close>. In |
|
742 |
practice, long names usually represent 1--3 levels of qualification. User ML |
|
743 |
code should not make any assumptions about the particular structure of long |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
744 |
names! |
20437 | 745 |
|
61854 | 746 |
The empty name is commonly used as an indication of unnamed entities, or |
747 |
entities that are not entered into the corresponding name space, whenever |
|
748 |
this makes any sense. The basic operations on long names map empty names |
|
749 |
again to empty names. |
|
58618 | 750 |
\<close> |
20437 | 751 |
|
58618 | 752 |
text %mlref \<open> |
20476 | 753 |
\begin{mldecls} |
30365 | 754 |
@{index_ML Long_Name.base_name: "string -> string"} \\ |
755 |
@{index_ML Long_Name.qualifier: "string -> string"} \\ |
|
756 |
@{index_ML Long_Name.append: "string -> string -> string"} \\ |
|
757 |
@{index_ML Long_Name.implode: "string list -> string"} \\ |
|
758 |
@{index_ML Long_Name.explode: "string -> string list"} \\ |
|
20547 | 759 |
\end{mldecls} |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
760 |
|
69597 | 761 |
\<^descr> \<^ML>\<open>Long_Name.base_name\<close>~\<open>name\<close> returns the base name of a long name. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
762 |
|
69597 | 763 |
\<^descr> \<^ML>\<open>Long_Name.qualifier\<close>~\<open>name\<close> returns the qualifier of a long name. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
764 |
|
69597 | 765 |
\<^descr> \<^ML>\<open>Long_Name.append\<close>~\<open>name\<^sub>1 name\<^sub>2\<close> appends two long names. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
766 |
|
69597 | 767 |
\<^descr> \<^ML>\<open>Long_Name.implode\<close>~\<open>names\<close> and \<^ML>\<open>Long_Name.explode\<close>~\<open>name\<close> convert |
61854 | 768 |
between the packed string representation and the explicit list form of long |
769 |
names. |
|
58618 | 770 |
\<close> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
771 |
|
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
772 |
|
58618 | 773 |
subsection \<open>Name spaces \label{sec:name-space}\<close> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
774 |
|
61854 | 775 |
text \<open> |
776 |
A \<open>name space\<close> manages a collection of long names, together with a mapping |
|
777 |
between partially qualified external names and fully qualified internal |
|
778 |
names (in both directions). Note that the corresponding \<open>intern\<close> and |
|
779 |
\<open>extern\<close> operations are mostly used for parsing and printing only! The |
|
780 |
\<open>declare\<close> operation augments a name space according to the accesses |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
781 |
determined by a given binding, and a naming policy from the context. |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
782 |
|
61416 | 783 |
\<^medskip> |
61854 | 784 |
A \<open>binding\<close> specifies details about the prospective long name of a newly |
785 |
introduced formal entity. It consists of a base name, prefixes for |
|
786 |
qualification (separate ones for system infrastructure and user-space |
|
787 |
mechanisms), a slot for the original source position, and some additional |
|
788 |
flags. |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
789 |
|
61416 | 790 |
\<^medskip> |
61854 | 791 |
A \<open>naming\<close> provides some additional details for producing a long name from a |
792 |
binding. Normally, the naming is implicit in the theory or proof context. |
|
793 |
The \<open>full\<close> operation (and its variants for different context types) produces |
|
794 |
a fully qualified internal name to be entered into a name space. The main |
|
795 |
equation of this ``chemical reaction'' when binding new entities in a |
|
796 |
context is as follows: |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
797 |
|
61416 | 798 |
\<^medskip> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
799 |
\begin{tabular}{l} |
61493 | 800 |
\<open>binding + naming \<longrightarrow> long name + name space accesses\<close> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
801 |
\end{tabular} |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
802 |
|
61416 | 803 |
\<^bigskip> |
61854 | 804 |
As a general principle, there is a separate name space for each kind of |
805 |
formal entity, e.g.\ fact, logical constant, type constructor, type class. |
|
806 |
It is usually clear from the occurrence in concrete syntax (or from the |
|
807 |
scope) which kind of entity a name refers to. For example, the very same |
|
808 |
name \<open>c\<close> may be used uniformly for a constant, type constructor, and type |
|
809 |
class. |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
810 |
|
61854 | 811 |
There are common schemes to name derived entities systematically according |
812 |
to the name of the main logical entity involved, e.g.\ fact \<open>c.intro\<close> for a |
|
813 |
canonical introduction rule related to constant \<open>c\<close>. This technique of |
|
814 |
mapping names from one space into another requires some care in order to |
|
815 |
avoid conflicts. In particular, theorem names derived from a type |
|
816 |
constructor or type class should get an additional suffix in addition to the |
|
817 |
usual qualification. This leads to the following conventions for derived |
|
39839 | 818 |
names: |
819 |
||
61416 | 820 |
\<^medskip> |
39839 | 821 |
\begin{tabular}{ll} |
822 |
logical entity & fact name \\\hline |
|
61493 | 823 |
constant \<open>c\<close> & \<open>c.intro\<close> \\ |
824 |
type \<open>c\<close> & \<open>c_type.intro\<close> \\ |
|
825 |
class \<open>c\<close> & \<open>c_class.intro\<close> \\ |
|
39839 | 826 |
\end{tabular} |
58618 | 827 |
\<close> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
828 |
|
58618 | 829 |
text %mlref \<open> |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
830 |
\begin{mldecls} |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
831 |
@{index_ML_type binding} \\ |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
832 |
@{index_ML Binding.empty: binding} \\ |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
833 |
@{index_ML Binding.name: "string -> binding"} \\ |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
834 |
@{index_ML Binding.qualify: "bool -> string -> binding -> binding"} \\ |
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
835 |
@{index_ML Binding.prefix: "bool -> string -> binding -> binding"} \\ |
59859 | 836 |
@{index_ML Binding.concealed: "binding -> binding"} \\ |
43547
f3a8476285c6
clarified Binding.pretty/print: no quotes, only markup -- Binding.str_of is rendered obsolete;
wenzelm
parents:
43329
diff
changeset
|
837 |
@{index_ML Binding.print: "binding -> string"} \\ |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
838 |
\end{mldecls} |
20547 | 839 |
\begin{mldecls} |
33174 | 840 |
@{index_ML_type Name_Space.naming} \\ |
58668 | 841 |
@{index_ML Name_Space.global_naming: Name_Space.naming} \\ |
33174 | 842 |
@{index_ML Name_Space.add_path: "string -> Name_Space.naming -> Name_Space.naming"} \\ |
843 |
@{index_ML Name_Space.full_name: "Name_Space.naming -> binding -> string"} \\ |
|
20547 | 844 |
\end{mldecls} |
845 |
\begin{mldecls} |
|
33174 | 846 |
@{index_ML_type Name_Space.T} \\ |
847 |
@{index_ML Name_Space.empty: "string -> Name_Space.T"} \\ |
|
848 |
@{index_ML Name_Space.merge: "Name_Space.T * Name_Space.T -> Name_Space.T"} \\ |
|
47174 | 849 |
@{index_ML Name_Space.declare: "Context.generic -> bool -> |
850 |
binding -> Name_Space.T -> string * Name_Space.T"} \\ |
|
33174 | 851 |
@{index_ML Name_Space.intern: "Name_Space.T -> string -> string"} \\ |
42358
b47d41d9f4b5
Name_Space: proper configuration options long_names, short_names, unique_names instead of former unsynchronized references;
wenzelm
parents:
40964
diff
changeset
|
852 |
@{index_ML Name_Space.extern: "Proof.context -> Name_Space.T -> string -> string"} \\ |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
853 |
@{index_ML Name_Space.is_concealed: "Name_Space.T -> string -> bool"} |
20476 | 854 |
\end{mldecls} |
20437 | 855 |
|
69597 | 856 |
\<^descr> Type \<^ML_type>\<open>binding\<close> represents the abstract concept of name bindings. |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
857 |
|
69597 | 858 |
\<^descr> \<^ML>\<open>Binding.empty\<close> is the empty binding. |
20476 | 859 |
|
69597 | 860 |
\<^descr> \<^ML>\<open>Binding.name\<close>~\<open>name\<close> produces a binding with base name \<open>name\<close>. Note |
61854 | 861 |
that this lacks proper source position information; see also the ML |
862 |
antiquotation @{ML_antiquotation binding}. |
|
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
863 |
|
69597 | 864 |
\<^descr> \<^ML>\<open>Binding.qualify\<close>~\<open>mandatory name binding\<close> prefixes qualifier \<open>name\<close> |
61854 | 865 |
to \<open>binding\<close>. The \<open>mandatory\<close> flag tells if this name component always needs |
866 |
to be given in name space accesses --- this is mostly \<open>false\<close> in practice. |
|
867 |
Note that this part of qualification is typically used in derived |
|
868 |
specification mechanisms. |
|
20437 | 869 |
|
69597 | 870 |
\<^descr> \<^ML>\<open>Binding.prefix\<close> is similar to \<^ML>\<open>Binding.qualify\<close>, but affects the |
61854 | 871 |
system prefix. This part of extra qualification is typically used in the |
872 |
infrastructure for modular specifications, notably ``local theory targets'' |
|
873 |
(see also \chref{ch:local-theory}). |
|
20437 | 874 |
|
69597 | 875 |
\<^descr> \<^ML>\<open>Binding.concealed\<close>~\<open>binding\<close> indicates that the binding shall refer |
61854 | 876 |
to an entity that serves foundational purposes only. This flag helps to mark |
877 |
implementation details of specification mechanism etc. Other tools should |
|
69597 | 878 |
not depend on the particulars of concealed entities (cf.\ \<^ML>\<open>Name_Space.is_concealed\<close>). |
34927
c4c02ac736a6
more details on long names, binding/naming, name space;
wenzelm
parents:
34926
diff
changeset
|
879 |
|
69597 | 880 |
\<^descr> \<^ML>\<open>Binding.print\<close>~\<open>binding\<close> produces a string representation for |
61854 | 881 |
human-readable output, together with some formal markup that might get used |
882 |
in GUI front-ends, for example. |
|
20476 | 883 |
|
69597 | 884 |
\<^descr> Type \<^ML_type>\<open>Name_Space.naming\<close> represents the abstract concept of a |
61854 | 885 |
naming policy. |
20437 | 886 |
|
69597 | 887 |
\<^descr> \<^ML>\<open>Name_Space.global_naming\<close> is the default naming policy: it is global |
61854 | 888 |
and lacks any path prefix. In a regular theory context this is augmented by |
889 |
a path prefix consisting of the theory name. |
|
20476 | 890 |
|
69597 | 891 |
\<^descr> \<^ML>\<open>Name_Space.add_path\<close>~\<open>path naming\<close> augments the naming policy by |
61854 | 892 |
extending its path component. |
20437 | 893 |
|
69597 | 894 |
\<^descr> \<^ML>\<open>Name_Space.full_name\<close>~\<open>naming binding\<close> turns a name binding (usually |
61854 | 895 |
a basic name) into the fully qualified internal name, according to the given |
896 |
naming policy. |
|
20476 | 897 |
|
69597 | 898 |
\<^descr> Type \<^ML_type>\<open>Name_Space.T\<close> represents name spaces. |
20476 | 899 |
|
69597 | 900 |
\<^descr> \<^ML>\<open>Name_Space.empty\<close>~\<open>kind\<close> and \<^ML>\<open>Name_Space.merge\<close>~\<open>(space\<^sub>1, |
61854 | 901 |
space\<^sub>2)\<close> are the canonical operations for maintaining name spaces according |
902 |
to theory data management (\secref{sec:context-data}); \<open>kind\<close> is a formal |
|
903 |
comment to characterize the purpose of a name space. |
|
20437 | 904 |
|
69597 | 905 |
\<^descr> \<^ML>\<open>Name_Space.declare\<close>~\<open>context strict binding space\<close> enters a name |
61854 | 906 |
binding as fully qualified internal name into the name space, using the |
907 |
naming of the context. |
|
20476 | 908 |
|
69597 | 909 |
\<^descr> \<^ML>\<open>Name_Space.intern\<close>~\<open>space name\<close> internalizes a (partially qualified) |
61854 | 910 |
external name. |
20437 | 911 |
|
61854 | 912 |
This operation is mostly for parsing! Note that fully qualified names |
69597 | 913 |
stemming from declarations are produced via \<^ML>\<open>Name_Space.full_name\<close> and |
914 |
\<^ML>\<open>Name_Space.declare\<close> (or their derivatives for \<^ML_type>\<open>theory\<close> and |
|
915 |
\<^ML_type>\<open>Proof.context\<close>). |
|
20437 | 916 |
|
69597 | 917 |
\<^descr> \<^ML>\<open>Name_Space.extern\<close>~\<open>ctxt space name\<close> externalizes a (fully qualified) |
61854 | 918 |
internal name. |
20476 | 919 |
|
61854 | 920 |
This operation is mostly for printing! User code should not rely on the |
921 |
precise result too much. |
|
20476 | 922 |
|
69597 | 923 |
\<^descr> \<^ML>\<open>Name_Space.is_concealed\<close>~\<open>space name\<close> indicates whether \<open>name\<close> refers |
61854 | 924 |
to a strictly private entity that other tools are supposed to ignore! |
58618 | 925 |
\<close> |
30272 | 926 |
|
58618 | 927 |
text %mlantiq \<open> |
39832 | 928 |
\begin{matharray}{rcl} |
61493 | 929 |
@{ML_antiquotation_def "binding"} & : & \<open>ML_antiquotation\<close> \\ |
39832 | 930 |
\end{matharray} |
931 |
||
69597 | 932 |
\<^rail>\<open> |
67146 | 933 |
@@{ML_antiquotation binding} embedded |
69597 | 934 |
\<close> |
39832 | 935 |
|
61854 | 936 |
\<^descr> \<open>@{binding name}\<close> produces a binding with base name \<open>name\<close> and the source |
937 |
position taken from the concrete syntax of this antiquotation. In many |
|
69597 | 938 |
situations this is more appropriate than the more basic \<^ML>\<open>Binding.name\<close> |
61854 | 939 |
function. |
58618 | 940 |
\<close> |
39832 | 941 |
|
61854 | 942 |
text %mlex \<open> |
943 |
The following example yields the source position of some concrete binding |
|
944 |
inlined into the text: |
|
58618 | 945 |
\<close> |
39833 | 946 |
|
69597 | 947 |
ML_val \<open>Binding.pos_of \<^binding>\<open>here\<close>\<close> |
39833 | 948 |
|
61416 | 949 |
text \<open> |
950 |
\<^medskip> |
|
61854 | 951 |
That position can be also printed in a message as follows: |
952 |
\<close> |
|
39833 | 953 |
|
58742 | 954 |
ML_command |
955 |
\<open>writeln |
|
69597 | 956 |
("Look here" ^ Position.here (Binding.pos_of \<^binding>\<open>here\<close>))\<close> |
39833 | 957 |
|
61854 | 958 |
text \<open> |
959 |
This illustrates a key virtue of formalized bindings as opposed to raw |
|
960 |
specifications of base names: the system can use this additional information |
|
961 |
for feedback given to the user (error messages etc.). |
|
56071 | 962 |
|
61416 | 963 |
\<^medskip> |
61854 | 964 |
The following example refers to its source position directly, which is |
965 |
occasionally useful for experimentation and diagnostic purposes: |
|
966 |
\<close> |
|
56071 | 967 |
|
69597 | 968 |
ML_command \<open>warning ("Look here" ^ Position.here \<^here>)\<close> |
39833 | 969 |
|
18537 | 970 |
end |