author | wenzelm |
Mon, 14 Jul 2008 17:51:48 +0200 | |
changeset 27579 | 97ce525f664c |
parent 27557 | 151731493264 |
child 27609 | b23c9ad0fe7d |
permissions | -rw-r--r-- |
26513 | 1 |
|
20948 | 2 |
(* $Id$ *) |
3 |
||
21147 | 4 |
(*<*) |
20948 | 5 |
theory Codegen |
6 |
imports Main |
|
21452 | 7 |
uses "../../../antiquote_setup.ML" |
20948 | 8 |
begin |
9 |
||
27103 | 10 |
ML {* CodeTarget.code_width := 74 *} |
21147 | 11 |
|
12 |
(*>*) |
|
13 |
||
20948 | 14 |
chapter {* Code generation from Isabelle theories *} |
15 |
||
16 |
section {* Introduction *} |
|
17 |
||
21058 | 18 |
subsection {* Motivation *} |
19 |
||
20948 | 20 |
text {* |
21058 | 21 |
Executing formal specifications as programs is a well-established |
22 |
topic in the theorem proving community. With increasing |
|
23 |
application of theorem proving systems in the area of |
|
24 |
software development and verification, its relevance manifests |
|
25 |
for running test cases and rapid prototyping. In logical |
|
26 |
calculi like constructive type theory, |
|
27 |
a notion of executability is implicit due to the nature |
|
22550 | 28 |
of the calculus. In contrast, specifications in Isabelle |
21058 | 29 |
can be highly non-executable. In order to bridge |
30 |
the gap between logic and executable specifications, |
|
31 |
an explicit non-trivial transformation has to be applied: |
|
32 |
code generation. |
|
33 |
||
34 |
This tutorial introduces a generic code generator for the |
|
35 |
Isabelle system \cite{isa-tutorial}. |
|
36 |
Generic in the sense that the |
|
37 |
\qn{target language} for which code shall ultimately be |
|
38 |
generated is not fixed but may be an arbitrary state-of-the-art |
|
39 |
functional programming language (currently, the implementation |
|
22550 | 40 |
supports SML \cite{SML}, OCaml \cite{OCaml} and Haskell |
41 |
\cite{haskell-revised-report}). |
|
21058 | 42 |
We aim to provide a |
43 |
versatile environment |
|
44 |
suitable for software development and verification, |
|
45 |
structuring the process |
|
46 |
of code generation into a small set of orthogonal principles |
|
47 |
while achieving a big coverage of application areas |
|
48 |
with maximum flexibility. |
|
21189 | 49 |
|
22550 | 50 |
Conceptually the code generator framework is part |
51 |
of Isabelle's @{text Pure} meta logic; the object logic |
|
52 |
@{text HOL} which is an extension of @{text Pure} |
|
53 |
already comes with a reasonable framework setup and thus provides |
|
54 |
a good working horse for raising code-generation-driven |
|
55 |
applications. So, we assume some familiarity and experience |
|
56 |
with the ingredients of the @{text HOL} \emph{Main} theory |
|
57 |
(see also \cite{isa-tutorial}). |
|
21058 | 58 |
*} |
59 |
||
60 |
||
61 |
subsection {* Overview *} |
|
62 |
||
63 |
text {* |
|
64 |
The code generator aims to be usable with no further ado |
|
65 |
in most cases while allowing for detailed customization. |
|
22550 | 66 |
This manifests in the structure of this tutorial: |
67 |
we start with a generic example \secref{sec:example} |
|
68 |
and introduce code generation concepts \secref{sec:concept}. |
|
69 |
Section |
|
21178 | 70 |
\secref{sec:basics} explains how to use the framework naively, |
21058 | 71 |
presuming a reasonable default setup. Then, section |
72 |
\secref{sec:advanced} deals with advanced topics, |
|
73 |
introducing further aspects of the code generator framework |
|
74 |
in a motivation-driven manner. Last, section \secref{sec:ml} |
|
75 |
introduces the framework's internal programming interfaces. |
|
20948 | 76 |
|
21058 | 77 |
\begin{warn} |
78 |
Ultimately, the code generator which this tutorial deals with |
|
79 |
is supposed to replace the already established code generator |
|
80 |
by Stefan Berghofer \cite{Berghofer-Nipkow:2002}. |
|
21147 | 81 |
So, for the moment, there are two distinct code generators |
21058 | 82 |
in Isabelle. |
22916 | 83 |
Also note that while the framework itself is |
22550 | 84 |
object-logic independent, only @{text HOL} provides a reasonable |
21058 | 85 |
framework setup. |
86 |
\end{warn} |
|
87 |
*} |
|
88 |
||
89 |
||
22550 | 90 |
section {* An example: a simple theory of search trees \label{sec:example} *} |
91 |
||
92 |
text {* |
|
22916 | 93 |
When writing executable specifications using @{text HOL}, |
94 |
it is convenient to use |
|
22550 | 95 |
three existing packages: the datatype package for defining |
96 |
datatypes, the function package for (recursive) functions, |
|
97 |
and the class package for overloaded definitions. |
|
98 |
||
99 |
We develope a small theory of search trees; trees are represented |
|
100 |
as a datatype with key type @{typ "'a"} and value type @{typ "'b"}: |
|
101 |
*} |
|
22479 | 102 |
|
103 |
datatype ('a, 'b) searchtree = Leaf "'a\<Colon>linorder" 'b |
|
104 |
| Branch "('a, 'b) searchtree" "'a" "('a, 'b) searchtree" |
|
105 |
||
22550 | 106 |
text {* |
107 |
\noindent Note that we have constrained the type of keys |
|
108 |
to the class of total orders, @{text linorder}. |
|
109 |
||
110 |
We define @{text find} and @{text update} functions: |
|
111 |
*} |
|
112 |
||
25870 | 113 |
primrec |
22479 | 114 |
find :: "('a\<Colon>linorder, 'b) searchtree \<Rightarrow> 'a \<Rightarrow> 'b option" where |
115 |
"find (Leaf key val) it = (if it = key then Some val else None)" |
|
116 |
| "find (Branch t1 key t2) it = (if it \<le> key then find t1 it else find t2 it)" |
|
117 |
||
118 |
fun |
|
119 |
update :: "'a\<Colon>linorder \<times> 'b \<Rightarrow> ('a, 'b) searchtree \<Rightarrow> ('a, 'b) searchtree" where |
|
120 |
"update (it, entry) (Leaf key val) = ( |
|
121 |
if it = key then Leaf key entry |
|
122 |
else if it \<le> key |
|
123 |
then Branch (Leaf it entry) it (Leaf key val) |
|
124 |
else Branch (Leaf key val) it (Leaf it entry) |
|
125 |
)" |
|
126 |
| "update (it, entry) (Branch t1 key t2) = ( |
|
127 |
if it \<le> key |
|
128 |
then (Branch (update (it, entry) t1) key t2) |
|
129 |
else (Branch t1 key (update (it, entry) t2)) |
|
130 |
)" |
|
131 |
||
22550 | 132 |
text {* |
133 |
\noindent For testing purpose, we define a small example |
|
134 |
using natural numbers @{typ nat} (which are a @{text linorder}) |
|
23130 | 135 |
as keys and list of nats as values: |
22550 | 136 |
*} |
137 |
||
23130 | 138 |
definition |
139 |
example :: "(nat, nat list) searchtree" |
|
140 |
where |
|
141 |
"example = update (Suc (Suc (Suc (Suc 0))), [Suc (Suc 0), Suc (Suc 0)]) (update (Suc (Suc (Suc 0)), [Suc (Suc (Suc 0))]) |
|
142 |
(update (Suc (Suc 0), [Suc (Suc 0)]) (Leaf (Suc 0) [])))" |
|
22479 | 143 |
|
22550 | 144 |
text {* |
145 |
\noindent Then we generate code |
|
146 |
*} |
|
147 |
||
26999 | 148 |
export_code example (*<*)in SML (*>*)in SML file "examples/tree.ML" |
22479 | 149 |
|
150 |
text {* |
|
22550 | 151 |
\noindent which looks like: |
22479 | 152 |
\lstsml{Thy/examples/tree.ML} |
153 |
*} |
|
154 |
||
22550 | 155 |
|
156 |
section {* Code generation concepts and process \label{sec:concept} *} |
|
21058 | 157 |
|
158 |
text {* |
|
21189 | 159 |
\begin{figure}[h] |
160 |
\centering |
|
161 |
\includegraphics[width=0.7\textwidth]{codegen_process} |
|
162 |
\caption{code generator -- processing overview} |
|
163 |
\label{fig:process} |
|
164 |
\end{figure} |
|
165 |
||
21058 | 166 |
The code generator employs a notion of executability |
167 |
for three foundational executable ingredients known |
|
168 |
from functional programming: |
|
22060 | 169 |
\emph{defining equations}, \emph{datatypes}, and |
170 |
\emph{type classes}. A defining equation as a first approximation |
|
21058 | 171 |
is a theorem of the form @{text "f t\<^isub>1 t\<^isub>2 \<dots> t\<^isub>n \<equiv> t"} |
172 |
(an equation headed by a constant @{text f} with arguments |
|
22798 | 173 |
@{text "t\<^isub>1 t\<^isub>2 \<dots> t\<^isub>n"} and right hand side @{text t}). |
22060 | 174 |
Code generation aims to turn defining equations |
21058 | 175 |
into a functional program by running through |
176 |
a process (see figure \ref{fig:process}): |
|
177 |
||
178 |
\begin{itemize} |
|
179 |
||
180 |
\item Out of the vast collection of theorems proven in a |
|
181 |
\qn{theory}, a reasonable subset modeling |
|
22060 | 182 |
defining equations is \qn{selected}. |
21058 | 183 |
|
184 |
\item On those selected theorems, certain |
|
185 |
transformations are carried out |
|
186 |
(\qn{preprocessing}). Their purpose is to turn theorems |
|
187 |
representing non- or badly executable |
|
188 |
specifications into equivalent but executable counterparts. |
|
189 |
The result is a structured collection of \qn{code theorems}. |
|
190 |
||
22479 | 191 |
\item These \qn{code theorems} then are \qn{translated} |
21058 | 192 |
into an Haskell-like intermediate |
193 |
language. |
|
194 |
||
195 |
\item Finally, out of the intermediate language the final |
|
196 |
code in the desired \qn{target language} is \qn{serialized}. |
|
197 |
||
198 |
\end{itemize} |
|
199 |
||
200 |
From these steps, only the two last are carried out |
|
201 |
outside the logic; by keeping this layer as |
|
202 |
thin as possible, the amount of code to trust is |
|
203 |
kept to a minimum. |
|
204 |
*} |
|
205 |
||
206 |
||
207 |
||
208 |
section {* Basics \label{sec:basics} *} |
|
20948 | 209 |
|
210 |
subsection {* Invoking the code generator *} |
|
211 |
||
21058 | 212 |
text {* |
22916 | 213 |
Thanks to a reasonable setup of the @{text HOL} theories, in |
21058 | 214 |
most cases code generation proceeds without further ado: |
215 |
*} |
|
216 |
||
25870 | 217 |
primrec |
22473 | 218 |
fac :: "nat \<Rightarrow> nat" where |
219 |
"fac 0 = 1" |
|
220 |
| "fac (Suc n) = Suc n * fac n" |
|
21058 | 221 |
|
222 |
text {* |
|
22550 | 223 |
\noindent This executable specification is now turned to SML code: |
21058 | 224 |
*} |
225 |
||
24348 | 226 |
export_code fac (*<*)in SML(*>*)in SML file "examples/fac.ML" |
21058 | 227 |
|
228 |
text {* |
|
24348 | 229 |
\noindent The @{text "\<EXPORTCODE>"} command takes a space-separated list of |
21058 | 230 |
constants together with \qn{serialization directives} |
22845 | 231 |
These start with a \qn{target language} |
232 |
identifier, followed by a file specification |
|
233 |
where to write the generated code to. |
|
21058 | 234 |
|
22060 | 235 |
Internally, the defining equations for all selected |
21178 | 236 |
constants are taken, including any transitively required |
21058 | 237 |
constants, datatypes and classes, resulting in the following |
238 |
code: |
|
239 |
||
240 |
\lstsml{Thy/examples/fac.ML} |
|
241 |
||
242 |
The code generator will complain when a required |
|
22550 | 243 |
ingredient does not provide a executable counterpart, |
244 |
e.g.~generating code |
|
21058 | 245 |
for constants not yielding |
22550 | 246 |
a defining equation (e.g.~the Hilbert choice |
247 |
operation @{text "SOME"}): |
|
21058 | 248 |
*} |
249 |
(*<*) |
|
250 |
setup {* Sign.add_path "foo" *} |
|
251 |
(*>*) |
|
252 |
definition |
|
21993 | 253 |
pick_some :: "'a list \<Rightarrow> 'a" where |
21058 | 254 |
"pick_some xs = (SOME x. x \<in> set xs)" |
255 |
(*<*) |
|
256 |
hide const pick_some |
|
257 |
||
258 |
setup {* Sign.parent_path *} |
|
259 |
||
260 |
definition |
|
21993 | 261 |
pick_some :: "'a list \<Rightarrow> 'a" where |
21058 | 262 |
"pick_some = hd" |
263 |
(*>*) |
|
25870 | 264 |
|
24348 | 265 |
export_code pick_some in SML file "examples/fail_const.ML" |
21058 | 266 |
|
22550 | 267 |
text {* \noindent will fail. *} |
268 |
||
20948 | 269 |
subsection {* Theorem selection *} |
270 |
||
21058 | 271 |
text {* |
22060 | 272 |
The list of all defining equations in a theory may be inspected |
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
273 |
using the @{text "\<PRINTCODESETUP>"} command: |
21058 | 274 |
*} |
275 |
||
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
276 |
print_codesetup |
21058 | 277 |
|
278 |
text {* |
|
279 |
\noindent which displays a table of constant with corresponding |
|
22060 | 280 |
defining equations (the additional stuff displayed |
22751 | 281 |
shall not bother us for the moment). |
21058 | 282 |
|
22916 | 283 |
The typical @{text HOL} tools are already set up in a way that |
22751 | 284 |
function definitions introduced by @{text "\<DEFINITION>"}, |
25870 | 285 |
@{text "\<PRIMREC>"}, @{text "\<FUN>"}, |
286 |
@{text "\<FUNCTION>"}, @{text "\<CONSTDEFS>"}, |
|
21323 | 287 |
@{text "\<RECDEF>"} are implicitly propagated |
22060 | 288 |
to this defining equation table. Specific theorems may be |
21058 | 289 |
selected using an attribute: \emph{code func}. As example, |
290 |
a weight selector function: |
|
291 |
*} |
|
292 |
||
293 |
primrec |
|
25870 | 294 |
pick :: "(nat \<times> 'a) list \<Rightarrow> nat \<Rightarrow> 'a" where |
21058 | 295 |
"pick (x#xs) n = (let (k, v) = x in |
296 |
if n < k then v else pick xs (n - k))" |
|
297 |
||
298 |
text {* |
|
22798 | 299 |
\noindent We want to eliminate the explicit destruction |
21058 | 300 |
of @{term x} to @{term "(k, v)"}: |
301 |
*} |
|
302 |
||
303 |
lemma [code func]: |
|
304 |
"pick ((k, v)#xs) n = (if n < k then v else pick xs (n - k))" |
|
305 |
by simp |
|
306 |
||
24348 | 307 |
export_code pick (*<*)in SML(*>*) in SML file "examples/pick1.ML" |
21058 | 308 |
|
309 |
text {* |
|
22798 | 310 |
\noindent This theorem now is used for generating code: |
21058 | 311 |
|
312 |
\lstsml{Thy/examples/pick1.ML} |
|
313 |
||
22798 | 314 |
\noindent It might be convenient to remove the pointless original |
22845 | 315 |
equation, using the \emph{func del} attribute: |
21058 | 316 |
*} |
317 |
||
22845 | 318 |
lemmas [code func del] = pick.simps |
21058 | 319 |
|
24348 | 320 |
export_code pick (*<*)in SML(*>*) in SML file "examples/pick2.ML" |
21058 | 321 |
|
322 |
text {* |
|
323 |
\lstsml{Thy/examples/pick2.ML} |
|
324 |
||
22798 | 325 |
\noindent Syntactic redundancies are implicitly dropped. For example, |
21058 | 326 |
using a modified version of the @{const fac} function |
22060 | 327 |
as defining equation, the then redundant (since |
328 |
syntactically subsumed) original defining equations |
|
21058 | 329 |
are dropped, resulting in a warning: |
330 |
*} |
|
331 |
||
332 |
lemma [code func]: |
|
333 |
"fac n = (case n of 0 \<Rightarrow> 1 | Suc m \<Rightarrow> n * fac m)" |
|
334 |
by (cases n) simp_all |
|
335 |
||
24348 | 336 |
export_code fac (*<*)in SML(*>*)in SML file "examples/fac_case.ML" |
21058 | 337 |
|
338 |
text {* |
|
339 |
\lstsml{Thy/examples/fac_case.ML} |
|
340 |
||
341 |
\begin{warn} |
|
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
342 |
The attributes \emph{code} and \emph{code del} |
21058 | 343 |
associated with the existing code generator also apply to |
344 |
the new one: \emph{code} implies \emph{code func}, |
|
22845 | 345 |
and \emph{code del} implies \emph{code func del}. |
21058 | 346 |
\end{warn} |
347 |
*} |
|
20948 | 348 |
|
349 |
subsection {* Type classes *} |
|
350 |
||
21058 | 351 |
text {* |
352 |
Type classes enter the game via the Isar class package. |
|
21075 | 353 |
For a short introduction how to use it, see \cite{isabelle-classes}; |
21147 | 354 |
here we just illustrate its impact on code generation. |
21058 | 355 |
|
356 |
In a target language, type classes may be represented |
|
22798 | 357 |
natively (as in the case of Haskell). For languages |
21058 | 358 |
like SML, they are implemented using \emph{dictionaries}. |
21178 | 359 |
Our following example specifies a class \qt{null}, |
21058 | 360 |
assigning to each of its inhabitants a \qt{null} value: |
361 |
*} |
|
362 |
||
22473 | 363 |
class null = type + |
21058 | 364 |
fixes null :: 'a |
365 |
||
25870 | 366 |
primrec |
367 |
head :: "'a\<Colon>null list \<Rightarrow> 'a" where |
|
21058 | 368 |
"head [] = null" |
22798 | 369 |
| "head (x#xs) = x" |
21058 | 370 |
|
371 |
text {* |
|
25533 | 372 |
\noindent We provide some instances for our @{text null}: |
21058 | 373 |
*} |
374 |
||
25533 | 375 |
instantiation option and list :: (type) null |
376 |
begin |
|
377 |
||
378 |
definition |
|
379 |
"null = None" |
|
21058 | 380 |
|
25533 | 381 |
definition |
382 |
"null = []" |
|
383 |
||
384 |
instance .. |
|
385 |
||
386 |
end |
|
21058 | 387 |
|
388 |
text {* |
|
25533 | 389 |
\noindent Constructing a dummy example: |
21058 | 390 |
*} |
391 |
||
392 |
definition |
|
393 |
"dummy = head [Some (Suc 0), None]" |
|
394 |
||
395 |
text {* |
|
21178 | 396 |
Type classes offer a suitable occasion to introduce |
21058 | 397 |
the Haskell serializer. Its usage is almost the same |
21075 | 398 |
as SML, but, in accordance with conventions |
399 |
some Haskell systems enforce, each module ends |
|
400 |
up in a single file. The module hierarchy is reflected in |
|
22845 | 401 |
the file system, with root directory given as file specification. |
21058 | 402 |
*} |
403 |
||
24348 | 404 |
export_code dummy in Haskell file "examples/" |
21147 | 405 |
(* NOTE: you may use Haskell only once in this document, otherwise |
406 |
you have to work in distinct subdirectories *) |
|
21058 | 407 |
|
408 |
text {* |
|
409 |
\lsthaskell{Thy/examples/Codegen.hs} |
|
22798 | 410 |
\noindent (we have left out all other modules). |
21058 | 411 |
|
22798 | 412 |
\medskip |
21058 | 413 |
|
414 |
The whole code in SML with explicit dictionary passing: |
|
415 |
*} |
|
416 |
||
24348 | 417 |
export_code dummy (*<*)in SML(*>*)in SML file "examples/class.ML" |
21058 | 418 |
|
419 |
text {* |
|
420 |
\lstsml{Thy/examples/class.ML} |
|
421 |
||
22798 | 422 |
\medskip |
423 |
||
424 |
\noindent or in OCaml: |
|
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
425 |
*} |
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
426 |
|
24348 | 427 |
export_code dummy in OCaml file "examples/class.ocaml" |
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
428 |
|
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
429 |
text {* |
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
430 |
\lstsml{Thy/examples/class.ocaml} |
22798 | 431 |
|
432 |
\medskip The explicit association of constants |
|
433 |
to classes can be inspected using the @{text "\<PRINTCLASSES>"} |
|
22845 | 434 |
command. |
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
435 |
*} |
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
436 |
|
22550 | 437 |
|
21058 | 438 |
section {* Recipes and advanced topics \label{sec:advanced} *} |
439 |
||
21089 | 440 |
text {* |
441 |
In this tutorial, we do not attempt to give an exhaustive |
|
442 |
description of the code generator framework; instead, |
|
443 |
we cast a light on advanced topics by introducing |
|
444 |
them together with practically motivated examples. Concerning |
|
445 |
further reading, see |
|
446 |
||
447 |
\begin{itemize} |
|
448 |
||
449 |
\item the Isabelle/Isar Reference Manual \cite{isabelle-isar-ref} |
|
450 |
for exhaustive syntax diagrams. |
|
24193 | 451 |
\item or \cite{Haftmann-Nipkow:2007:codegen} which deals with foundational issues |
21089 | 452 |
of the code generator framework. |
453 |
||
454 |
\end{itemize} |
|
455 |
*} |
|
21058 | 456 |
|
22798 | 457 |
subsection {* Library theories \label{sec:library} *} |
21058 | 458 |
|
21089 | 459 |
text {* |
22916 | 460 |
The @{text HOL} @{text Main} theory already provides a code |
461 |
generator setup |
|
21089 | 462 |
which should be suitable for most applications. Common extensions |
22916 | 463 |
and modifications are available by certain theories of the @{text HOL} |
21089 | 464 |
library; beside being useful in applications, they may serve |
21178 | 465 |
as a tutorial for customizing the code generator setup. |
21089 | 466 |
|
467 |
\begin{description} |
|
468 |
||
24994
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
469 |
\item[@{text "Code_Integer"}] represents @{text HOL} integers by big |
22798 | 470 |
integer literals in target languages. |
24994
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
471 |
\item[@{text "Code_Char"}] represents @{text HOL} characters by |
22798 | 472 |
character literals in target languages. |
24994
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
473 |
\item[@{text "Code_Char_chr"}] like @{text "Code_Char"}, |
22798 | 474 |
but also offers treatment of character codes; includes |
24994
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
475 |
@{text "Code_Integer"}. |
23850 | 476 |
\item[@{text "Efficient_Nat"}] \label{eff_nat} implements natural numbers by integers, |
21178 | 477 |
which in general will result in higher efficency; pattern |
25369
5200374fda5d
replaced @{const} (allows name only) by proper @{term};
wenzelm
parents:
24994
diff
changeset
|
478 |
matching with @{term "0\<Colon>nat"} / @{const "Suc"} |
24994
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
479 |
is eliminated; includes @{text "Code_Integer"}. |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
480 |
\item[@{text "Code_Index"}] provides an additional datatype |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
481 |
@{text index} which is mapped to target-language built-in integers. |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
482 |
Useful for code setups which involve e.g. indexing of |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
483 |
target-language arrays. |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
484 |
\item[@{text "Code_Message"}] provides an additional datatype |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
485 |
@{text message_string} which is isomorphic to strings; |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
486 |
@{text message_string}s are mapped to target-language strings. |
c385c4eabb3b
consolidated naming conventions for code generator theories
haftmann
parents:
24628
diff
changeset
|
487 |
Useful for code setups which involve e.g. printing (error) messages. |
21089 | 488 |
|
489 |
\end{description} |
|
22916 | 490 |
|
491 |
\begin{warn} |
|
492 |
When importing any of these theories, they should form the last |
|
493 |
items in an import list. Since these theories adapt the |
|
494 |
code generator setup in a non-conservative fashion, |
|
495 |
strange effects may occur otherwise. |
|
496 |
\end{warn} |
|
21089 | 497 |
*} |
498 |
||
20948 | 499 |
subsection {* Preprocessing *} |
500 |
||
21089 | 501 |
text {* |
21147 | 502 |
Before selected function theorems are turned into abstract |
503 |
code, a chain of definitional transformation steps is carried |
|
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
504 |
out: \emph{preprocessing}. In essence, the preprocessort |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
505 |
consists of two components: a \emph{simpset} and \emph{function transformators}. |
21147 | 506 |
|
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
507 |
The \emph{simpset} allows to employ the full generality of the Isabelle |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
508 |
simplifier. Due to the interpretation of theorems |
22060 | 509 |
of defining equations, rewrites are applied to the right |
21147 | 510 |
hand side and the arguments of the left hand side of an |
511 |
equation, but never to the constant heading the left hand side. |
|
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
512 |
An important special case are \emph{inline theorems} which may be |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
513 |
declared an undeclared using the |
22845 | 514 |
\emph{code inline} or \emph{code inline del} attribute respectively. |
21147 | 515 |
Some common applications: |
516 |
*} |
|
517 |
||
518 |
text_raw {* |
|
519 |
\begin{itemize} |
|
520 |
*} |
|
521 |
||
22845 | 522 |
text {* |
523 |
\item replacing non-executable constructs by executable ones: |
|
524 |
*} |
|
21147 | 525 |
|
22845 | 526 |
lemma [code inline]: |
527 |
"x \<in> set xs \<longleftrightarrow> x mem xs" by (induct xs) simp_all |
|
528 |
||
529 |
text {* |
|
530 |
\item eliminating superfluous constants: |
|
21089 | 531 |
*} |
532 |
||
22845 | 533 |
lemma [code inline]: |
534 |
"1 = Suc 0" by simp |
|
535 |
||
536 |
text {* |
|
537 |
\item replacing executable but inconvenient constructs: |
|
538 |
*} |
|
539 |
||
540 |
lemma [code inline]: |
|
541 |
"xs = [] \<longleftrightarrow> List.null xs" by (induct xs) simp_all |
|
21147 | 542 |
|
543 |
text_raw {* |
|
544 |
\end{itemize} |
|
545 |
*} |
|
546 |
||
547 |
text {* |
|
548 |
||
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
549 |
\emph{Function transformators} provide a most general interface, |
21147 | 550 |
transforming a list of function theorems to another |
551 |
list of function theorems, provided that neither the heading |
|
25369
5200374fda5d
replaced @{const} (allows name only) by proper @{term};
wenzelm
parents:
24994
diff
changeset
|
552 |
constant nor its type change. The @{term "0\<Colon>nat"} / @{const Suc} |
21323 | 553 |
pattern elimination implemented in |
21452 | 554 |
theory @{text "EfficientNat"} (\secref{eff_nat}) uses this |
21147 | 555 |
interface. |
556 |
||
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
557 |
\noindent The current setup of the preprocessor may be inspected using |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
558 |
the @{text "\<PRINTCODESETUP>"} command. |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
559 |
|
21147 | 560 |
\begin{warn} |
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
561 |
Preprocessing is \emph{no} fix point process. Keep this in mind when |
21147 | 562 |
setting up the preprocessor. |
563 |
||
564 |
Further, the attribute \emph{code unfold} |
|
565 |
associated with the existing code generator also applies to |
|
566 |
the new one: \emph{code unfold} implies \emph{code inline}. |
|
567 |
\end{warn} |
|
568 |
*} |
|
20948 | 569 |
|
22798 | 570 |
|
571 |
subsection {* Concerning operational equality *} |
|
572 |
||
573 |
text {* |
|
574 |
Surely you have already noticed how equality is treated |
|
575 |
by the code generator: |
|
576 |
*} |
|
577 |
||
25870 | 578 |
primrec |
22798 | 579 |
collect_duplicates :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
580 |
"collect_duplicates xs ys [] = xs" |
|
581 |
| "collect_duplicates xs ys (z#zs) = (if z \<in> set xs |
|
582 |
then if z \<in> set ys |
|
583 |
then collect_duplicates xs ys zs |
|
584 |
else collect_duplicates xs (z#ys) zs |
|
585 |
else collect_duplicates (z#xs) (z#ys) zs)" |
|
586 |
||
587 |
text {* |
|
588 |
The membership test during preprocessing is rewritten, |
|
23850 | 589 |
resulting in @{const List.member}, which itself |
22798 | 590 |
performs an explicit equality check. |
591 |
*} |
|
592 |
||
24348 | 593 |
export_code collect_duplicates (*<*)in SML(*>*)in SML file "examples/collect_duplicates.ML" |
22798 | 594 |
|
595 |
text {* |
|
596 |
\lstsml{Thy/examples/collect_duplicates.ML} |
|
597 |
*} |
|
598 |
||
599 |
text {* |
|
600 |
Obviously, polymorphic equality is implemented the Haskell |
|
26513 | 601 |
way using a type class. How is this achieved? HOL introduces |
602 |
an explicit class @{text eq} with a corresponding operation |
|
26732 | 603 |
@{const eq_class.eq} such that @{thm eq [no_vars]}. |
26513 | 604 |
The preprocessing framework does the rest. |
22798 | 605 |
For datatypes, instances of @{text eq} are implicitly derived |
26513 | 606 |
when possible. For other types, you may instantiate @{text eq} |
607 |
manually like any other type class. |
|
22798 | 608 |
|
609 |
Though this @{text eq} class is designed to get rarely in |
|
610 |
the way, a subtlety |
|
611 |
enters the stage when definitions of overloaded constants |
|
612 |
are dependent on operational equality. For example, let |
|
613 |
us define a lexicographic ordering on tuples: |
|
614 |
*} |
|
26513 | 615 |
|
25870 | 616 |
instantiation * :: (ord, ord) ord |
617 |
begin |
|
618 |
||
619 |
definition |
|
620 |
[code func del]: "p1 < p2 \<longleftrightarrow> (let (x1, y1) = p1; (x2, y2) = p2 in |
|
621 |
x1 < x2 \<or> (x1 = x2 \<and> y1 < y2))" |
|
22798 | 622 |
|
25870 | 623 |
definition |
624 |
[code func del]: "p1 \<le> p2 \<longleftrightarrow> (let (x1, y1) = p1; (x2, y2) = p2 in |
|
625 |
x1 < x2 \<or> (x1 = x2 \<and> y1 \<le> y2))" |
|
626 |
||
627 |
instance .. |
|
628 |
||
629 |
end |
|
22798 | 630 |
|
22845 | 631 |
lemma ord_prod [code func(*<*), code func del(*>*)]: |
22798 | 632 |
"(x1 \<Colon> 'a\<Colon>ord, y1 \<Colon> 'b\<Colon>ord) < (x2, y2) \<longleftrightarrow> x1 < x2 \<or> (x1 = x2 \<and> y1 < y2)" |
633 |
"(x1 \<Colon> 'a\<Colon>ord, y1 \<Colon> 'b\<Colon>ord) \<le> (x2, y2) \<longleftrightarrow> x1 < x2 \<or> (x1 = x2 \<and> y1 \<le> y2)" |
|
634 |
unfolding less_prod_def less_eq_prod_def by simp_all |
|
635 |
||
636 |
text {* |
|
637 |
Then code generation will fail. Why? The definition |
|
25369
5200374fda5d
replaced @{const} (allows name only) by proper @{term};
wenzelm
parents:
24994
diff
changeset
|
638 |
of @{term "op \<le>"} depends on equality on both arguments, |
22798 | 639 |
which are polymorphic and impose an additional @{text eq} |
640 |
class constraint, thus violating the type discipline |
|
641 |
for class operations. |
|
642 |
||
643 |
The solution is to add @{text eq} explicitly to the first sort arguments in the |
|
644 |
code theorems: |
|
645 |
*} |
|
646 |
||
647 |
lemma ord_prod_code [code func]: |
|
648 |
"(x1 \<Colon> 'a\<Colon>{ord, eq}, y1 \<Colon> 'b\<Colon>ord) < (x2, y2) \<longleftrightarrow> |
|
649 |
x1 < x2 \<or> (x1 = x2 \<and> y1 < y2)" |
|
650 |
"(x1 \<Colon> 'a\<Colon>{ord, eq}, y1 \<Colon> 'b\<Colon>ord) \<le> (x2, y2) \<longleftrightarrow> |
|
651 |
x1 < x2 \<or> (x1 = x2 \<and> y1 \<le> y2)" |
|
652 |
unfolding ord_prod by rule+ |
|
653 |
||
654 |
text {* |
|
655 |
\noindent Then code generation succeeds: |
|
656 |
*} |
|
657 |
||
24348 | 658 |
export_code "op \<le> \<Colon> 'a\<Colon>{eq, ord} \<times> 'b\<Colon>ord \<Rightarrow> 'a \<times> 'b \<Rightarrow> bool" |
22845 | 659 |
(*<*)in SML(*>*)in SML file "examples/lexicographic.ML" |
22798 | 660 |
|
661 |
text {* |
|
662 |
\lstsml{Thy/examples/lexicographic.ML} |
|
663 |
*} |
|
664 |
||
665 |
text {* |
|
666 |
In general, code theorems for overloaded constants may have more |
|
667 |
restrictive sort constraints than the underlying instance relation |
|
668 |
between class and type constructor as long as the whole system of |
|
669 |
constraints is coregular; code theorems violating coregularity |
|
670 |
are rejected immediately. Consequently, it might be necessary |
|
671 |
to delete disturbing theorems in the code theorem table, |
|
672 |
as we have done here with the original definitions @{text less_prod_def} |
|
673 |
and @{text less_eq_prod_def}. |
|
22885 | 674 |
|
675 |
In some cases, the automatically derived defining equations |
|
676 |
for equality on a particular type may not be appropriate. |
|
677 |
As example, watch the following datatype representing |
|
23130 | 678 |
monomorphic parametric types (where type constructors |
679 |
are referred to by natural numbers): |
|
22798 | 680 |
*} |
681 |
||
23130 | 682 |
datatype monotype = Mono nat "monotype list" |
22885 | 683 |
(*<*) |
684 |
lemma monotype_eq: |
|
685 |
"Mono tyco1 typargs1 = Mono tyco2 typargs2 \<equiv> |
|
686 |
tyco1 = tyco2 \<and> typargs1 = typargs2" by simp |
|
687 |
(*>*) |
|
688 |
||
689 |
text {* |
|
690 |
Then code generation for SML would fail with a message |
|
691 |
that the generated code conains illegal mutual dependencies: |
|
23130 | 692 |
the theorem @{thm monotype_eq [no_vars]} already requires the |
22885 | 693 |
instance @{text "monotype \<Colon> eq"}, which itself requires |
23130 | 694 |
@{thm monotype_eq [no_vars]}; Haskell has no problem with mutually |
22885 | 695 |
recursive @{text instance} and @{text function} definitions, |
696 |
but the SML serializer does not support this. |
|
697 |
||
698 |
In such cases, you have to provide you own equality equations |
|
699 |
involving auxiliary constants. In our case, |
|
700 |
@{const [show_types] list_all2} can do the job: |
|
701 |
*} |
|
702 |
||
703 |
lemma monotype_eq_list_all2 [code func]: |
|
704 |
"Mono tyco1 typargs1 = Mono tyco2 typargs2 \<longleftrightarrow> |
|
705 |
tyco1 = tyco2 \<and> list_all2 (op =) typargs1 typargs2" |
|
706 |
by (simp add: list_all2_eq [symmetric]) |
|
707 |
||
708 |
text {* |
|
709 |
does not depend on instance @{text "monotype \<Colon> eq"}: |
|
710 |
*} |
|
711 |
||
24348 | 712 |
export_code "op = :: monotype \<Rightarrow> monotype \<Rightarrow> bool" |
22885 | 713 |
(*<*)in SML(*>*)in SML file "examples/monotype.ML" |
714 |
||
715 |
text {* |
|
716 |
\lstsml{Thy/examples/monotype.ML} |
|
717 |
*} |
|
22798 | 718 |
|
719 |
subsection {* Programs as sets of theorems *} |
|
720 |
||
721 |
text {* |
|
722 |
As told in \secref{sec:concept}, code generation is based |
|
723 |
on a structured collection of code theorems. |
|
724 |
For explorative purpose, this collection |
|
725 |
may be inspected using the @{text "\<CODETHMS>"} command: |
|
726 |
*} |
|
727 |
||
728 |
code_thms "op mod :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
729 |
||
730 |
text {* |
|
731 |
\noindent prints a table with \emph{all} defining equations |
|
25369
5200374fda5d
replaced @{const} (allows name only) by proper @{term};
wenzelm
parents:
24994
diff
changeset
|
732 |
for @{term "op mod :: nat \<Rightarrow> nat \<Rightarrow> nat"}, including |
22798 | 733 |
\emph{all} defining equations those equations depend |
734 |
on recursivly. @{text "\<CODETHMS>"} provides a convenient |
|
735 |
mechanism to inspect the impact of a preprocessor setup |
|
736 |
on defining equations. |
|
737 |
||
738 |
Similarly, the @{text "\<CODEDEPS>"} command shows a graph |
|
739 |
visualizing dependencies between defining equations. |
|
740 |
*} |
|
741 |
||
742 |
||
25411 | 743 |
subsection {* Constructor sets for datatypes *} |
744 |
||
745 |
text {* |
|
746 |
Conceptually, any datatype is spanned by a set of |
|
747 |
\emph{constructors} of type @{text "\<tau> = \<dots> \<Rightarrow> \<kappa> \<alpha>\<^isub>1 \<dots> \<alpha>\<^isub>n"} |
|
748 |
where @{text "{\<alpha>\<^isub>1, \<dots>, \<alpha>\<^isub>n}"} is excactly the set of \emph{all} |
|
749 |
type variables in @{text "\<tau>"}. The HOL datatype package |
|
750 |
by default registers any new datatype in the table |
|
751 |
of datatypes, which may be inspected using |
|
752 |
the @{text "\<PRINTCODESETUP>"} command. |
|
753 |
||
754 |
In some cases, it may be convenient to alter or |
|
26999 | 755 |
extend this table; as an example, we will develope an alternative |
756 |
representation of natural numbers as binary digits, whose |
|
757 |
size does increase logarithmically with its value, not linear |
|
758 |
\footnote{Indeed, the @{text "Efficient_Nat"} theory \ref{eff_nat} |
|
759 |
does something similar}. First, the digit representation: |
|
760 |
*} |
|
761 |
||
762 |
definition Dig0 :: "nat \<Rightarrow> nat" where |
|
763 |
"Dig0 n = 2 * n" |
|
764 |
||
765 |
definition Dig1 :: "nat \<Rightarrow> nat" where |
|
766 |
"Dig1 n = Suc (2 * n)" |
|
767 |
||
768 |
text {* |
|
769 |
\noindent We will use these two ">digits"< to represent natural numbers |
|
770 |
in binary digits, e.g.: |
|
771 |
*} |
|
772 |
||
773 |
lemma 42: "42 = Dig0 (Dig1 (Dig0 (Dig1 (Dig0 1))))" |
|
774 |
by (simp add: Dig0_def Dig1_def) |
|
775 |
||
776 |
text {* |
|
777 |
\noindent Of course we also have to provide proper code equations for |
|
778 |
the operations, e.g. @{term "op + \<Colon> nat \<Rightarrow> nat \<Rightarrow> nat"}: |
|
26973 | 779 |
*} |
25411 | 780 |
|
26999 | 781 |
lemma plus_Dig [code func]: |
782 |
"0 + n = n" |
|
783 |
"m + 0 = m" |
|
784 |
"1 + Dig0 n = Dig1 n" |
|
785 |
"Dig0 m + 1 = Dig1 m" |
|
786 |
"1 + Dig1 n = Dig0 (n + 1)" |
|
787 |
"Dig1 m + 1 = Dig0 (m + 1)" |
|
788 |
"Dig0 m + Dig0 n = Dig0 (m + n)" |
|
789 |
"Dig0 m + Dig1 n = Dig1 (m + n)" |
|
790 |
"Dig1 m + Dig0 n = Dig1 (m + n)" |
|
791 |
"Dig1 m + Dig1 n = Dig0 (m + n + 1)" |
|
792 |
by (simp_all add: Dig0_def Dig1_def) |
|
793 |
||
794 |
text {* |
|
795 |
\noindent We then instruct the code generator to view @{term "0\<Colon>nat"}, |
|
796 |
@{term "1\<Colon>nat"}, @{term Dig0} and @{term Dig1} as |
|
797 |
datatype constructors: |
|
798 |
*} |
|
799 |
||
800 |
code_datatype "0\<Colon>nat" "1\<Colon>nat" Dig0 Dig1 |
|
25411 | 801 |
|
26999 | 802 |
text {* |
803 |
\noindent For the former constructor @{term Suc}, we provide a code |
|
804 |
equation and remove some parts of the default code generator setup |
|
805 |
which are an obstacle here: |
|
806 |
*} |
|
807 |
||
808 |
lemma Suc_Dig [code func]: |
|
809 |
"Suc n = n + 1" |
|
810 |
by simp |
|
25411 | 811 |
|
26999 | 812 |
declare One_nat_def [code inline del] |
813 |
declare add_Suc_shift [code func del] |
|
814 |
||
815 |
text {* |
|
816 |
\noindent This yields the following code: |
|
817 |
*} |
|
818 |
||
819 |
export_code "op + \<Colon> nat \<Rightarrow> nat \<Rightarrow> nat" (*<*)in SML(*>*) in SML file "examples/nat_binary.ML" |
|
820 |
||
821 |
text {* \lstsml{Thy/examples/nat_binary.ML} *} |
|
25411 | 822 |
|
823 |
text {* |
|
824 |
\medskip |
|
825 |
||
26999 | 826 |
From this example, it can be easily glimpsed that using own constructor sets |
827 |
is a little delicate since it changes the set of valid patterns for values |
|
828 |
of that type. Without going into much detail, here some practical hints: |
|
829 |
||
830 |
\begin{itemize} |
|
831 |
\item When changing the constuctor set for datatypes, take care to |
|
832 |
provide an alternative for the @{text case} combinator (e.g. by replacing |
|
833 |
it using the preprocessor). |
|
834 |
\item Values in the target language need not to be normalized -- different |
|
835 |
values in the target language may represent the same value in the |
|
836 |
logic (e.g. @{text "Dig1 0 = 1"}). |
|
837 |
\item Usually, a good methodology to deal with the subleties of pattern |
|
838 |
matching is to see the type as an abstract type: provide a set |
|
839 |
of operations which operate on the concrete representation of the type, |
|
840 |
and derive further operations by combinations of these primitive ones, |
|
841 |
without relying on a particular representation. |
|
842 |
\end{itemize} |
|
25411 | 843 |
*} |
844 |
||
26999 | 845 |
code_datatype %invisible "0::nat" Suc |
846 |
declare %invisible plus_Dig [code func del] |
|
847 |
declare %invisible One_nat_def [code inline] |
|
848 |
declare %invisible add_Suc_shift [code func] |
|
849 |
lemma %invisible [code func]: "0 + n = (n \<Colon> nat)" by simp |
|
850 |
||
25411 | 851 |
|
21058 | 852 |
subsection {* Customizing serialization *} |
20948 | 853 |
|
22798 | 854 |
subsubsection {* Basics *} |
855 |
||
21147 | 856 |
text {* |
857 |
Consider the following function and its corresponding |
|
858 |
SML code: |
|
859 |
*} |
|
860 |
||
25870 | 861 |
primrec |
21147 | 862 |
in_interval :: "nat \<times> nat \<Rightarrow> nat \<Rightarrow> bool" where |
863 |
"in_interval (k, l) n \<longleftrightarrow> k \<le> n \<and> n \<le> l" |
|
864 |
(*<*) |
|
21323 | 865 |
code_type %tt bool |
21147 | 866 |
(SML) |
21323 | 867 |
code_const %tt True and False and "op \<and>" and Not |
21147 | 868 |
(SML and and and) |
869 |
(*>*) |
|
24348 | 870 |
export_code in_interval (*<*)in SML(*>*)in SML file "examples/bool_literal.ML" |
21147 | 871 |
|
872 |
text {* |
|
21323 | 873 |
\lstsml{Thy/examples/bool_literal.ML} |
21147 | 874 |
|
22798 | 875 |
\noindent Though this is correct code, it is a little bit unsatisfactory: |
21147 | 876 |
boolean values and operators are materialized as distinguished |
877 |
entities with have nothing to do with the SML-builtin notion |
|
878 |
of \qt{bool}. This results in less readable code; |
|
879 |
additionally, eager evaluation may cause programs to |
|
880 |
loop or break which would perfectly terminate when |
|
881 |
the existing SML \qt{bool} would be used. To map |
|
882 |
the HOL \qt{bool} on SML \qt{bool}, we may use |
|
883 |
\qn{custom serializations}: |
|
884 |
*} |
|
885 |
||
21323 | 886 |
code_type %tt bool |
21147 | 887 |
(SML "bool") |
21323 | 888 |
code_const %tt True and False and "op \<and>" |
21147 | 889 |
(SML "true" and "false" and "_ andalso _") |
890 |
||
891 |
text {* |
|
21323 | 892 |
The @{text "\<CODETYPE>"} commad takes a type constructor |
21147 | 893 |
as arguments together with a list of custom serializations. |
894 |
Each custom serialization starts with a target language |
|
895 |
identifier followed by an expression, which during |
|
896 |
code serialization is inserted whenever the type constructor |
|
21323 | 897 |
would occur. For constants, @{text "\<CODECONST>"} implements |
898 |
the corresponding mechanism. Each ``@{verbatim "_"}'' in |
|
21147 | 899 |
a serialization expression is treated as a placeholder |
900 |
for the type constructor's (the constant's) arguments. |
|
901 |
*} |
|
902 |
||
24348 | 903 |
export_code in_interval (*<*)in SML(*>*) in SML file "examples/bool_mlbool.ML" |
21147 | 904 |
|
905 |
text {* |
|
21323 | 906 |
\lstsml{Thy/examples/bool_mlbool.ML} |
21147 | 907 |
|
22798 | 908 |
\noindent This still is not perfect: the parentheses |
21323 | 909 |
around the \qt{andalso} expression are superfluous. |
910 |
Though the serializer |
|
21147 | 911 |
by no means attempts to imitate the rich Isabelle syntax |
912 |
framework, it provides some common idioms, notably |
|
913 |
associative infixes with precedences which may be used here: |
|
914 |
*} |
|
915 |
||
21323 | 916 |
code_const %tt "op \<and>" |
21147 | 917 |
(SML infixl 1 "andalso") |
918 |
||
24348 | 919 |
export_code in_interval (*<*)in SML(*>*) in SML file "examples/bool_infix.ML" |
21147 | 920 |
|
921 |
text {* |
|
21323 | 922 |
\lstsml{Thy/examples/bool_infix.ML} |
21147 | 923 |
|
22798 | 924 |
\medskip |
925 |
||
21147 | 926 |
Next, we try to map HOL pairs to SML pairs, using the |
21323 | 927 |
infix ``@{verbatim "*"}'' type constructor and parentheses: |
21147 | 928 |
*} |
929 |
(*<*) |
|
930 |
code_type * |
|
931 |
(SML) |
|
932 |
code_const Pair |
|
933 |
(SML) |
|
934 |
(*>*) |
|
21323 | 935 |
code_type %tt * |
21147 | 936 |
(SML infix 2 "*") |
21323 | 937 |
code_const %tt Pair |
21147 | 938 |
(SML "!((_),/ (_))") |
939 |
||
940 |
text {* |
|
21323 | 941 |
The initial bang ``@{verbatim "!"}'' tells the serializer to never put |
21147 | 942 |
parentheses around the whole expression (they are already present), |
943 |
while the parentheses around argument place holders |
|
944 |
tell not to put parentheses around the arguments. |
|
21323 | 945 |
The slash ``@{verbatim "/"}'' (followed by arbitrary white space) |
21147 | 946 |
inserts a space which may be used as a break if necessary |
947 |
during pretty printing. |
|
948 |
||
22798 | 949 |
These examples give a glimpse what mechanisms |
21178 | 950 |
custom serializations provide; however their usage |
951 |
requires careful thinking in order not to introduce |
|
952 |
inconsistencies -- or, in other words: |
|
953 |
custom serializations are completely axiomatic. |
|
21147 | 954 |
|
21178 | 955 |
A further noteworthy details is that any special |
956 |
character in a custom serialization may be quoted |
|
21323 | 957 |
using ``@{verbatim "'"}''; thus, in |
958 |
``@{verbatim "fn '_ => _"}'' the first |
|
959 |
``@{verbatim "_"}'' is a proper underscore while the |
|
960 |
second ``@{verbatim "_"}'' is a placeholder. |
|
21147 | 961 |
|
21178 | 962 |
The HOL theories provide further |
25411 | 963 |
examples for custom serializations. |
21178 | 964 |
*} |
21147 | 965 |
|
22188
a63889770d57
adjusted manual to improved treatment of overloaded constants
haftmann
parents:
22175
diff
changeset
|
966 |
|
21178 | 967 |
subsubsection {* Haskell serialization *} |
968 |
||
969 |
text {* |
|
970 |
For convenience, the default |
|
971 |
HOL setup for Haskell maps the @{text eq} class to |
|
972 |
its counterpart in Haskell, giving custom serializations |
|
21323 | 973 |
for the class (@{text "\<CODECLASS>"}) and its operation: |
21178 | 974 |
*} |
975 |
||
21323 | 976 |
code_class %tt eq |
22798 | 977 |
(Haskell "Eq" where "op =" \<equiv> "(==)") |
21178 | 978 |
|
22798 | 979 |
code_const %tt "op =" |
21178 | 980 |
(Haskell infixl 4 "==") |
981 |
||
982 |
text {* |
|
983 |
A problem now occurs whenever a type which |
|
984 |
is an instance of @{text eq} in HOL is mapped |
|
985 |
on a Haskell-builtin type which is also an instance |
|
986 |
of Haskell @{text Eq}: |
|
21147 | 987 |
*} |
988 |
||
21178 | 989 |
typedecl bar |
990 |
||
26513 | 991 |
instantiation bar :: eq |
992 |
begin |
|
993 |
||
26732 | 994 |
definition "eq_class.eq (x\<Colon>bar) y \<longleftrightarrow> x = y" |
26513 | 995 |
|
996 |
instance by default (simp add: eq_bar_def) |
|
997 |
||
998 |
end |
|
21178 | 999 |
|
21323 | 1000 |
code_type %tt bar |
21178 | 1001 |
(Haskell "Integer") |
1002 |
||
1003 |
text {* |
|
22188
a63889770d57
adjusted manual to improved treatment of overloaded constants
haftmann
parents:
22175
diff
changeset
|
1004 |
The code generator would produce |
a63889770d57
adjusted manual to improved treatment of overloaded constants
haftmann
parents:
22175
diff
changeset
|
1005 |
an additional instance, which of course is rejected. |
a63889770d57
adjusted manual to improved treatment of overloaded constants
haftmann
parents:
22175
diff
changeset
|
1006 |
To suppress this additional instance, use |
a63889770d57
adjusted manual to improved treatment of overloaded constants
haftmann
parents:
22175
diff
changeset
|
1007 |
@{text "\<CODEINSTANCE>"}: |
21147 | 1008 |
*} |
1009 |
||
21323 | 1010 |
code_instance %tt bar :: eq |
21178 | 1011 |
(Haskell -) |
1012 |
||
1013 |
||
22798 | 1014 |
subsubsection {* Pretty printing *} |
21189 | 1015 |
|
1016 |
text {* |
|
22798 | 1017 |
The serializer provides ML interfaces to set up |
1018 |
pretty serializations for expressions like lists, numerals |
|
1019 |
and characters; these are |
|
1020 |
monolithic stubs and should only be used with the |
|
1021 |
theories introduces in \secref{sec:library}. |
|
21189 | 1022 |
*} |
1023 |
||
22550 | 1024 |
|
21189 | 1025 |
subsection {* Cyclic module dependencies *} |
21178 | 1026 |
|
21189 | 1027 |
text {* |
1028 |
Sometimes the awkward situation occurs that dependencies |
|
1029 |
between definitions introduce cyclic dependencies |
|
1030 |
between modules, which in the Haskell world leaves |
|
1031 |
you to the mercy of the Haskell implementation you are using, |
|
1032 |
while for SML code generation is not possible. |
|
21178 | 1033 |
|
21189 | 1034 |
A solution is to declare module names explicitly. |
1035 |
Let use assume the three cyclically dependent |
|
1036 |
modules are named \emph{A}, \emph{B} and \emph{C}. |
|
1037 |
Then, by stating |
|
1038 |
*} |
|
1039 |
||
1040 |
code_modulename SML |
|
1041 |
A ABC |
|
1042 |
B ABC |
|
1043 |
C ABC |
|
1044 |
||
1045 |
text {* |
|
1046 |
we explicitly map all those modules on \emph{ABC}, |
|
1047 |
resulting in an ad-hoc merge of this three modules |
|
1048 |
at serialization time. |
|
1049 |
*} |
|
21147 | 1050 |
|
22798 | 1051 |
subsection {* Incremental code generation *} |
1052 |
||
1053 |
text {* |
|
1054 |
Code generation is \emph{incremental}: theorems |
|
1055 |
and abstract intermediate code are cached and extended on demand. |
|
1056 |
The cache may be partially or fully dropped if the underlying |
|
1057 |
executable content of the theory changes. |
|
1058 |
Implementation of caching is supposed to transparently |
|
1059 |
hid away the details from the user. Anyway, caching |
|
1060 |
reaches the surface by using a slightly more general form |
|
1061 |
of the @{text "\<CODETHMS>"}, @{text "\<CODEDEPS>"} |
|
24348 | 1062 |
and @{text "\<EXPORTCODE>"} commands: the list of constants |
22798 | 1063 |
may be omitted. Then, all constants with code theorems |
1064 |
in the current cache are referred to. |
|
1065 |
*} |
|
1066 |
||
25411 | 1067 |
(*subsection {* Code generation and proof extraction *} |
21189 | 1068 |
|
1069 |
text {* |
|
24217 | 1070 |
\fixme |
25411 | 1071 |
*}*) |
21189 | 1072 |
|
20948 | 1073 |
|
21058 | 1074 |
section {* ML interfaces \label{sec:ml} *} |
20948 | 1075 |
|
21189 | 1076 |
text {* |
1077 |
Since the code generator framework not only aims to provide |
|
1078 |
a nice Isar interface but also to form a base for |
|
1079 |
code-generation-based applications, here a short |
|
1080 |
description of the most important ML interfaces. |
|
1081 |
*} |
|
1082 |
||
24217 | 1083 |
subsection {* Executable theory content: @{text Code} *} |
21147 | 1084 |
|
1085 |
text {* |
|
1086 |
This Pure module implements the core notions of |
|
1087 |
executable content of a theory. |
|
1088 |
*} |
|
1089 |
||
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
1090 |
subsubsection {* Managing executable content *} |
20948 | 1091 |
|
21147 | 1092 |
text %mlref {* |
1093 |
\begin{mldecls} |
|
25369
5200374fda5d
replaced @{const} (allows name only) by proper @{term};
wenzelm
parents:
24994
diff
changeset
|
1094 |
@{index_ML Code.add_func: "thm -> theory -> theory"} \\ |
24217 | 1095 |
@{index_ML Code.del_func: "thm -> theory -> theory"} \\ |
24421 | 1096 |
@{index_ML Code.add_funcl: "string * thm list Susp.T -> theory -> theory"} \\ |
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1097 |
@{index_ML Code.map_pre: "(MetaSimplifier.simpset -> MetaSimplifier.simpset) -> theory -> theory"} \\ |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1098 |
@{index_ML Code.map_post: "(MetaSimplifier.simpset -> MetaSimplifier.simpset) -> theory -> theory"} \\ |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1099 |
@{index_ML Code.add_functrans: "string * (theory -> thm list -> thm list) |
21189 | 1100 |
-> theory -> theory"} \\ |
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1101 |
@{index_ML Code.del_functrans: "string -> theory -> theory"} \\ |
24421 | 1102 |
@{index_ML Code.add_datatype: "(string * typ) list -> theory -> theory"} \\ |
24217 | 1103 |
@{index_ML Code.get_datatype: "theory -> string |
22479 | 1104 |
-> (string * sort) list * (string * typ list) list"} \\ |
24421 | 1105 |
@{index_ML Code.get_datatype_of_constr: "theory -> string -> string option"} |
21147 | 1106 |
\end{mldecls} |
1107 |
||
1108 |
\begin{description} |
|
1109 |
||
24217 | 1110 |
\item @{ML Code.add_func}~@{text "thm"}~@{text "thy"} adds function |
21189 | 1111 |
theorem @{text "thm"} to executable content. |
1112 |
||
24217 | 1113 |
\item @{ML Code.del_func}~@{text "thm"}~@{text "thy"} removes function |
21189 | 1114 |
theorem @{text "thm"} from executable content, if present. |
1115 |
||
24217 | 1116 |
\item @{ML Code.add_funcl}~@{text "(const, lthms)"}~@{text "thy"} adds |
22060 | 1117 |
suspended defining equations @{text lthms} for constant |
21189 | 1118 |
@{text const} to executable content. |
1119 |
||
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1120 |
\item @{ML Code.map_pre}~@{text "f"}~@{text "thy"} changes |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1121 |
the preprocessor simpset. |
21189 | 1122 |
|
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1123 |
\item @{ML Code.add_functrans}~@{text "(name, f)"}~@{text "thy"} adds |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1124 |
function transformator @{text f} (named @{text name}) to executable content; |
22060 | 1125 |
@{text f} is a transformation of the defining equations belonging |
21189 | 1126 |
to a certain function definition, depending on the |
1127 |
current theory context. |
|
1128 |
||
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1129 |
\item @{ML Code.del_functrans}~@{text "name"}~@{text "thy"} removes |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1130 |
function transformator named @{text name} from executable content. |
22046 | 1131 |
|
24421 | 1132 |
\item @{ML Code.add_datatype}~@{text cs}~@{text thy} adds |
1133 |
a datatype to executable content, with generation |
|
1134 |
set @{text cs}. |
|
21189 | 1135 |
|
24217 | 1136 |
\item @{ML Code.get_datatype_of_constr}~@{text "thy"}~@{text "const"} |
21189 | 1137 |
returns type constructor corresponding to |
1138 |
constructor @{text const}; returns @{text NONE} |
|
1139 |
if @{text const} is no constructor. |
|
21147 | 1140 |
|
1141 |
\end{description} |
|
1142 |
*} |
|
1143 |
||
22292
3b118010ec08
adjusted to new code generator Isar commands and changes in implementation
haftmann
parents:
22188
diff
changeset
|
1144 |
subsection {* Auxiliary *} |
21147 | 1145 |
|
1146 |
text %mlref {* |
|
1147 |
\begin{mldecls} |
|
24421 | 1148 |
@{index_ML CodeUnit.read_const: "theory -> string -> string"} \\ |
26973 | 1149 |
@{index_ML CodeUnit.head_func: "thm -> string * ((string * sort) list * typ)"} \\ |
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1150 |
@{index_ML CodeUnit.rewrite_func: "MetaSimplifier.simpset -> thm -> thm"} \\ |
21147 | 1151 |
\end{mldecls} |
21217 | 1152 |
|
1153 |
\begin{description} |
|
1154 |
||
24217 | 1155 |
\item @{ML CodeUnit.read_const}~@{text thy}~@{text s} |
21217 | 1156 |
reads a constant as a concrete term expression @{text s}. |
1157 |
||
24217 | 1158 |
\item @{ML CodeUnit.head_func}~@{text thm} |
22751 | 1159 |
extracts the constant and its type from a defining equation @{text thm}. |
21217 | 1160 |
|
27557
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1161 |
\item @{ML CodeUnit.rewrite_func}~@{text ss}~@{text thm} |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1162 |
rewrites a defining equation @{text thm} with a simpset @{text ss}; |
151731493264
simpsets as pre/postprocessors; generic preprocessor now named function transformators
haftmann
parents:
27103
diff
changeset
|
1163 |
only arguments and right hand side are rewritten, |
22060 | 1164 |
not the head of the defining equation. |
21217 | 1165 |
|
1166 |
\end{description} |
|
1167 |
||
21147 | 1168 |
*} |
20948 | 1169 |
|
1170 |
subsection {* Implementing code generator applications *} |
|
1171 |
||
21147 | 1172 |
text {* |
21217 | 1173 |
Implementing code generator applications on top |
1174 |
of the framework set out so far usually not only |
|
1175 |
involves using those primitive interfaces |
|
1176 |
but also storing code-dependent data and various |
|
1177 |
other things. |
|
1178 |
||
21147 | 1179 |
\begin{warn} |
1180 |
Some interfaces discussed here have not reached |
|
1181 |
a final state yet. |
|
1182 |
Changes likely to occur in future. |
|
1183 |
\end{warn} |
|
1184 |
*} |
|
1185 |
||
1186 |
subsubsection {* Data depending on the theory's executable content *} |
|
1187 |
||
21217 | 1188 |
text {* |
21452 | 1189 |
Due to incrementality of code generation, changes in the |
1190 |
theory's executable content have to be propagated in a |
|
1191 |
certain fashion. Additionally, such changes may occur |
|
1192 |
not only during theory extension but also during theory |
|
1193 |
merge, which is a little bit nasty from an implementation |
|
1194 |
point of view. The framework provides a solution |
|
1195 |
to this technical challenge by providing a functorial |
|
1196 |
data slot @{ML_functor CodeDataFun}; on instantiation |
|
1197 |
of this functor, the following types and operations |
|
1198 |
are required: |
|
1199 |
||
21217 | 1200 |
\medskip |
1201 |
\begin{tabular}{l} |
|
1202 |
@{text "type T"} \\ |
|
1203 |
@{text "val empty: T"} \\ |
|
1204 |
@{text "val merge: Pretty.pp \<rightarrow> T * T \<rightarrow> T"} \\ |
|
24217 | 1205 |
@{text "val purge: theory option \<rightarrow> CodeUnit.const list option \<rightarrow> T \<rightarrow> T"} |
21217 | 1206 |
\end{tabular} |
1207 |
||
21452 | 1208 |
\begin{description} |
1209 |
||
1210 |
\item @{text T} the type of data to store. |
|
1211 |
||
1212 |
\item @{text empty} initial (empty) data. |
|
1213 |
||
1214 |
\item @{text merge} merging two data slots. |
|
1215 |
||
22798 | 1216 |
\item @{text purge}~@{text thy}~@{text consts} propagates changes in executable content; |
21452 | 1217 |
if possible, the current theory context is handed over |
1218 |
as argument @{text thy} (if there is no current theory context (e.g.~during |
|
22798 | 1219 |
theory merge, @{ML NONE}); @{text consts} indicates the kind |
21452 | 1220 |
of change: @{ML NONE} stands for a fundamental change |
22798 | 1221 |
which invalidates any existing code, @{text "SOME consts"} |
1222 |
hints that executable content for constants @{text consts} |
|
21452 | 1223 |
has changed. |
1224 |
||
1225 |
\end{description} |
|
1226 |
||
1227 |
An instance of @{ML_functor CodeDataFun} provides the following |
|
1228 |
interface: |
|
1229 |
||
21217 | 1230 |
\medskip |
1231 |
\begin{tabular}{l} |
|
1232 |
@{text "get: theory \<rightarrow> T"} \\ |
|
1233 |
@{text "change: theory \<rightarrow> (T \<rightarrow> T) \<rightarrow> T"} \\ |
|
1234 |
@{text "change_yield: theory \<rightarrow> (T \<rightarrow> 'a * T) \<rightarrow> 'a * T"} |
|
1235 |
\end{tabular} |
|
1236 |
||
1237 |
\begin{description} |
|
1238 |
||
21452 | 1239 |
\item @{text get} retrieval of the current data. |
1240 |
||
1241 |
\item @{text change} update of current data (cached!) |
|
1242 |
by giving a continuation. |
|
1243 |
||
1244 |
\item @{text change_yield} update with side result. |
|
21217 | 1245 |
|
1246 |
\end{description} |
|
1247 |
*} |
|
1248 |
||
24628 | 1249 |
(*subsubsection {* Datatype hooks *} |
21147 | 1250 |
|
21452 | 1251 |
text {* |
1252 |
Isabelle/HOL's datatype package provides a mechanism to |
|
1253 |
extend theories depending on datatype declarations: |
|
1254 |
\emph{datatype hooks}. For example, when declaring a new |
|
22060 | 1255 |
datatype, a hook proves defining equations for equality on |
21452 | 1256 |
that datatype (if possible). |
1257 |
*} |
|
1258 |
||
21217 | 1259 |
text %mlref {* |
1260 |
\begin{mldecls} |
|
21323 | 1261 |
@{index_ML_type DatatypeHooks.hook: "string list -> theory -> theory"} \\ |
21217 | 1262 |
@{index_ML DatatypeHooks.add: "DatatypeHooks.hook -> theory -> theory"} |
1263 |
\end{mldecls} |
|
21452 | 1264 |
|
1265 |
\begin{description} |
|
1266 |
||
1267 |
\item @{ML_type DatatypeHooks.hook} specifies the interface |
|
1268 |
of \emph{datatype hooks}: a theory update |
|
1269 |
depending on the list of newly introduced |
|
1270 |
datatype names. |
|
1271 |
||
1272 |
\item @{ML DatatypeHooks.add} adds a hook to the |
|
1273 |
chain of all hooks. |
|
1274 |
||
1275 |
\end{description} |
|
1276 |
*} |
|
1277 |
||
1278 |
subsubsection {* Trivial typedefs -- type copies *} |
|
1279 |
||
1280 |
text {* |
|
1281 |
Sometimes packages will introduce new types |
|
1282 |
as \emph{marked type copies} similar to Haskell's |
|
1283 |
@{text newtype} declaration (e.g. the HOL record package) |
|
1284 |
\emph{without} tinkering with the overhead of datatypes. |
|
1285 |
Technically, these type copies are trivial forms of typedefs. |
|
1286 |
Since these type copies in code generation view are nothing |
|
1287 |
else than datatypes, they have been given a own package |
|
1288 |
in order to faciliate code generation: |
|
21147 | 1289 |
*} |
21058 | 1290 |
|
21217 | 1291 |
text %mlref {* |
1292 |
\begin{mldecls} |
|
21452 | 1293 |
@{index_ML_type TypecopyPackage.info} \\ |
21217 | 1294 |
@{index_ML TypecopyPackage.add_typecopy: " |
1295 |
bstring * string list -> typ -> (bstring * bstring) option |
|
1296 |
-> theory -> (string * TypecopyPackage.info) * theory"} \\ |
|
1297 |
@{index_ML TypecopyPackage.get_typecopy_info: "theory |
|
1298 |
-> string -> TypecopyPackage.info option"} \\ |
|
1299 |
@{index_ML TypecopyPackage.get_spec: "theory -> string |
|
21452 | 1300 |
-> (string * sort) list * (string * typ list) list"} \\ |
1301 |
@{index_ML_type TypecopyPackage.hook: "string * TypecopyPackage.info -> theory -> theory"} \\ |
|
1302 |
@{index_ML TypecopyPackage.add_hook: |
|
1303 |
"TypecopyPackage.hook -> theory -> theory"} \\ |
|
21217 | 1304 |
\end{mldecls} |
21452 | 1305 |
|
1306 |
\begin{description} |
|
1307 |
||
1308 |
\item @{ML_type TypecopyPackage.info} a record containing |
|
1309 |
the specification and further data of a type copy. |
|
1310 |
||
1311 |
\item @{ML TypecopyPackage.add_typecopy} defines a new |
|
1312 |
type copy. |
|
1313 |
||
1314 |
\item @{ML TypecopyPackage.get_typecopy_info} retrieves |
|
1315 |
data of an existing type copy. |
|
1316 |
||
1317 |
\item @{ML TypecopyPackage.get_spec} retrieves datatype-like |
|
1318 |
specification of a type copy. |
|
1319 |
||
1320 |
\item @{ML_type TypecopyPackage.hook},~@{ML TypecopyPackage.add_hook} |
|
1321 |
provide a hook mechanism corresponding to the hook mechanism |
|
1322 |
on datatypes. |
|
1323 |
||
1324 |
\end{description} |
|
1325 |
*} |
|
1326 |
||
1327 |
subsubsection {* Unifying type copies and datatypes *} |
|
1328 |
||
1329 |
text {* |
|
1330 |
Since datatypes and type copies are mapped to the same concept (datatypes) |
|
1331 |
by code generation, the view on both is unified \qt{code types}: |
|
21217 | 1332 |
*} |
1333 |
||
1334 |
text %mlref {* |
|
1335 |
\begin{mldecls} |
|
21452 | 1336 |
@{index_ML_type DatatypeCodegen.hook: "(string * (bool * ((string * sort) list |
1337 |
* (string * typ list) list))) list |
|
21323 | 1338 |
-> theory -> theory"} \\ |
21217 | 1339 |
@{index_ML DatatypeCodegen.add_codetypes_hook_bootstrap: " |
1340 |
DatatypeCodegen.hook -> theory -> theory"} |
|
1341 |
\end{mldecls} |
|
1342 |
*} |
|
1343 |
||
21222 | 1344 |
text {* |
21452 | 1345 |
\begin{description} |
1346 |
||
1347 |
\item @{ML_type DatatypeCodegen.hook} specifies the code type hook |
|
1348 |
interface: a theory transformation depending on a list of |
|
1349 |
mutual recursive code types; each entry in the list |
|
1350 |
has the structure @{text "(name, (is_data, (vars, cons)))"} |
|
1351 |
where @{text name} is the name of the code type, @{text is_data} |
|
1352 |
is true iff @{text name} is a datatype rather then a type copy, |
|
1353 |
and @{text "(vars, cons)"} is the specification of the code type. |
|
1354 |
||
1355 |
\item @{ML DatatypeCodegen.add_codetypes_hook_bootstrap} adds a code |
|
1356 |
type hook; the hook is immediately processed for all already |
|
1357 |
existing datatypes, in blocks of mutual recursive datatypes, |
|
1358 |
where all datatypes a block depends on are processed before |
|
1359 |
the block. |
|
1360 |
||
1361 |
\end{description} |
|
24628 | 1362 |
*}*) |
21452 | 1363 |
|
24628 | 1364 |
text {* |
21452 | 1365 |
\emph{Happy proving, happy hacking!} |
21222 | 1366 |
*} |
21217 | 1367 |
|
20948 | 1368 |
end |