author | haftmann |
Fri, 13 Aug 2010 13:43:54 +0200 | |
changeset 38402 | 58fc3a3af71f |
parent 37610 | 1b09880d9734 |
child 38405 | 7935b334893e |
permissions | -rw-r--r-- |
28447 | 1 |
% |
2 |
\begin{isabellebody}% |
|
3 |
\def\isabellecontext{Introduction}% |
|
4 |
% |
|
5 |
\isadelimtheory |
|
6 |
% |
|
7 |
\endisadelimtheory |
|
8 |
% |
|
9 |
\isatagtheory |
|
10 |
\isacommand{theory}\isamarkupfalse% |
|
11 |
\ Introduction\isanewline |
|
12 |
\isakeyword{imports}\ Setup\isanewline |
|
13 |
\isakeyword{begin}% |
|
14 |
\endisatagtheory |
|
15 |
{\isafoldtheory}% |
|
16 |
% |
|
17 |
\isadelimtheory |
|
18 |
% |
|
19 |
\endisadelimtheory |
|
20 |
% |
|
21 |
\isamarkupsection{Introduction and Overview% |
|
22 |
} |
|
23 |
\isamarkuptrue% |
|
24 |
% |
|
25 |
\begin{isamarkuptext}% |
|
26 |
This tutorial introduces a generic code generator for the |
|
27 |
\isa{Isabelle} system. |
|
34155 | 28 |
The |
29 |
\qn{target language} for which code is |
|
30 |
generated is not fixed, but may be one of several |
|
31 |
functional programming languages (currently, the implementation |
|
28447 | 32 |
supports \isa{SML} \cite{SML}, \isa{OCaml} \cite{OCaml} and \isa{Haskell} |
33 |
\cite{haskell-revised-report}). |
|
34 |
||
35 |
Conceptually the code generator framework is part |
|
36 |
of Isabelle's \hyperlink{theory.Pure}{\mbox{\isa{Pure}}} meta logic framework; the logic |
|
34155 | 37 |
\hyperlink{theory.HOL}{\mbox{\isa{HOL}}} \cite{isa-tutorial}, which is an extension of \hyperlink{theory.Pure}{\mbox{\isa{Pure}}}, |
28447 | 38 |
already comes with a reasonable framework setup and thus provides |
34155 | 39 |
a good basis for creating code-generation-driven |
28447 | 40 |
applications. So, we assume some familiarity and experience |
41 |
with the ingredients of the \hyperlink{theory.HOL}{\mbox{\isa{HOL}}} distribution theories. |
|
42 |
||
43 |
The code generator aims to be usable with no further ado |
|
34155 | 44 |
in most cases, while allowing for detailed customisation. |
45 |
This can be seen in the structure of this tutorial: after a short |
|
28447 | 46 |
conceptual introduction with an example (\secref{sec:intro}), |
47 |
we discuss the generic customisation facilities (\secref{sec:program}). |
|
31050 | 48 |
A further section (\secref{sec:adaptation}) is dedicated to the matter of |
49 |
\qn{adaptation} to specific target language environments. After some |
|
28447 | 50 |
further issues (\secref{sec:further}) we conclude with an overview |
51 |
of some ML programming interfaces (\secref{sec:ml}). |
|
52 |
||
53 |
\begin{warn} |
|
54 |
Ultimately, the code generator which this tutorial deals with |
|
55 |
is supposed to replace the existing code generator |
|
56 |
by Stefan Berghofer \cite{Berghofer-Nipkow:2002}. |
|
57 |
So, for the moment, there are two distinct code generators |
|
58 |
in Isabelle. In case of ambiguity, we will refer to the framework |
|
59 |
described here as \isa{generic\ code\ generator}, to the |
|
60 |
other as \isa{SML\ code\ generator}. |
|
61 |
Also note that while the framework itself is |
|
62 |
object-logic independent, only \hyperlink{theory.HOL}{\mbox{\isa{HOL}}} provides a reasonable |
|
63 |
framework setup. |
|
64 |
\end{warn}% |
|
65 |
\end{isamarkuptext}% |
|
66 |
\isamarkuptrue% |
|
67 |
% |
|
68 |
\isamarkupsubsection{Code generation via shallow embedding \label{sec:intro}% |
|
69 |
} |
|
70 |
\isamarkuptrue% |
|
71 |
% |
|
72 |
\begin{isamarkuptext}% |
|
73 |
The key concept for understanding \isa{Isabelle}'s code generation is |
|
74 |
\emph{shallow embedding}, i.e.~logical entities like constants, types and |
|
75 |
classes are identified with corresponding concepts in the target language. |
|
76 |
||
77 |
Inside \hyperlink{theory.HOL}{\mbox{\isa{HOL}}}, the \hyperlink{command.datatype}{\mbox{\isa{\isacommand{datatype}}}} and |
|
78 |
\hyperlink{command.definition}{\mbox{\isa{\isacommand{definition}}}}/\hyperlink{command.primrec}{\mbox{\isa{\isacommand{primrec}}}}/\hyperlink{command.fun}{\mbox{\isa{\isacommand{fun}}}} declarations form |
|
79 |
the core of a functional programming language. The default code generator setup |
|
34155 | 80 |
transforms those into functional programs immediately. |
28447 | 81 |
This means that \qt{naive} code generation can proceed without further ado. |
82 |
For example, here a simple \qt{implementation} of amortised queues:% |
|
83 |
\end{isamarkuptext}% |
|
84 |
\isamarkuptrue% |
|
85 |
% |
|
28564 | 86 |
\isadelimquote |
28447 | 87 |
% |
28564 | 88 |
\endisadelimquote |
28447 | 89 |
% |
28564 | 90 |
\isatagquote |
28447 | 91 |
\isacommand{datatype}\isamarkupfalse% |
29798 | 92 |
\ {\isacharprime}a\ queue\ {\isacharequal}\ AQueue\ {\isachardoublequoteopen}{\isacharprime}a\ list{\isachardoublequoteclose}\ {\isachardoublequoteopen}{\isacharprime}a\ list{\isachardoublequoteclose}\isanewline |
28447 | 93 |
\isanewline |
94 |
\isacommand{definition}\isamarkupfalse% |
|
95 |
\ empty\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}{\isacharprime}a\ queue{\isachardoublequoteclose}\ \isakeyword{where}\isanewline |
|
29798 | 96 |
\ \ {\isachardoublequoteopen}empty\ {\isacharequal}\ AQueue\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharbrackleft}{\isacharbrackright}{\isachardoublequoteclose}\isanewline |
28447 | 97 |
\isanewline |
98 |
\isacommand{primrec}\isamarkupfalse% |
|
99 |
\ enqueue\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a\ queue\ {\isasymRightarrow}\ {\isacharprime}a\ queue{\isachardoublequoteclose}\ \isakeyword{where}\isanewline |
|
29798 | 100 |
\ \ {\isachardoublequoteopen}enqueue\ x\ {\isacharparenleft}AQueue\ xs\ ys{\isacharparenright}\ {\isacharequal}\ AQueue\ {\isacharparenleft}x\ {\isacharhash}\ xs{\isacharparenright}\ ys{\isachardoublequoteclose}\isanewline |
28447 | 101 |
\isanewline |
102 |
\isacommand{fun}\isamarkupfalse% |
|
103 |
\ dequeue\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}{\isacharprime}a\ queue\ {\isasymRightarrow}\ {\isacharprime}a\ option\ {\isasymtimes}\ {\isacharprime}a\ queue{\isachardoublequoteclose}\ \isakeyword{where}\isanewline |
|
29798 | 104 |
\ \ \ \ {\isachardoublequoteopen}dequeue\ {\isacharparenleft}AQueue\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharbrackleft}{\isacharbrackright}{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}None{\isacharcomma}\ AQueue\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharbrackleft}{\isacharbrackright}{\isacharparenright}{\isachardoublequoteclose}\isanewline |
105 |
\ \ {\isacharbar}\ {\isachardoublequoteopen}dequeue\ {\isacharparenleft}AQueue\ xs\ {\isacharparenleft}y\ {\isacharhash}\ ys{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}Some\ y{\isacharcomma}\ AQueue\ xs\ ys{\isacharparenright}{\isachardoublequoteclose}\isanewline |
|
106 |
\ \ {\isacharbar}\ {\isachardoublequoteopen}dequeue\ {\isacharparenleft}AQueue\ xs\ {\isacharbrackleft}{\isacharbrackright}{\isacharparenright}\ {\isacharequal}\isanewline |
|
107 |
\ \ \ \ \ \ {\isacharparenleft}case\ rev\ xs\ of\ y\ {\isacharhash}\ ys\ {\isasymRightarrow}\ {\isacharparenleft}Some\ y{\isacharcomma}\ AQueue\ {\isacharbrackleft}{\isacharbrackright}\ ys{\isacharparenright}{\isacharparenright}{\isachardoublequoteclose}% |
|
28564 | 108 |
\endisatagquote |
109 |
{\isafoldquote}% |
|
28447 | 110 |
% |
28564 | 111 |
\isadelimquote |
28447 | 112 |
% |
28564 | 113 |
\endisadelimquote |
28447 | 114 |
% |
115 |
\begin{isamarkuptext}% |
|
116 |
\noindent Then we can generate code e.g.~for \isa{SML} as follows:% |
|
117 |
\end{isamarkuptext}% |
|
118 |
\isamarkuptrue% |
|
119 |
% |
|
28564 | 120 |
\isadelimquote |
28447 | 121 |
% |
28564 | 122 |
\endisadelimquote |
28447 | 123 |
% |
28564 | 124 |
\isatagquote |
28447 | 125 |
\isacommand{export{\isacharunderscore}code}\isamarkupfalse% |
126 |
\ empty\ dequeue\ enqueue\ \isakeyword{in}\ SML\isanewline |
|
127 |
\ \ \isakeyword{module{\isacharunderscore}name}\ Example\ \isakeyword{file}\ {\isachardoublequoteopen}examples{\isacharslash}example{\isachardot}ML{\isachardoublequoteclose}% |
|
28564 | 128 |
\endisatagquote |
129 |
{\isafoldquote}% |
|
28447 | 130 |
% |
28564 | 131 |
\isadelimquote |
28447 | 132 |
% |
28564 | 133 |
\endisadelimquote |
28447 | 134 |
% |
135 |
\begin{isamarkuptext}% |
|
136 |
\noindent resulting in the following code:% |
|
137 |
\end{isamarkuptext}% |
|
138 |
\isamarkuptrue% |
|
139 |
% |
|
28564 | 140 |
\isadelimquote |
28447 | 141 |
% |
28564 | 142 |
\endisadelimquote |
28447 | 143 |
% |
28564 | 144 |
\isatagquote |
28447 | 145 |
% |
146 |
\begin{isamarkuptext}% |
|
28727 | 147 |
\isatypewriter% |
28447 | 148 |
\noindent% |
34155 | 149 |
\hspace*{0pt}structure Example :~sig\\ |
34179 | 150 |
\hspace*{0pt} ~val foldl :~('a -> 'b -> 'a) -> 'a -> 'b list -> 'a\\ |
34155 | 151 |
\hspace*{0pt} ~val rev :~'a list -> 'a list\\ |
34179 | 152 |
\hspace*{0pt} ~datatype 'a queue = AQueue of 'a list * 'a list\\ |
34155 | 153 |
\hspace*{0pt} ~val empty :~'a queue\\ |
154 |
\hspace*{0pt} ~val dequeue :~'a queue -> 'a option * 'a queue\\ |
|
155 |
\hspace*{0pt} ~val enqueue :~'a -> 'a queue -> 'a queue\\ |
|
156 |
\hspace*{0pt}end = struct\\ |
|
28714 | 157 |
\hspace*{0pt}\\ |
158 |
\hspace*{0pt}fun foldl f a [] = a\\ |
|
34179 | 159 |
\hspace*{0pt} ~| foldl f a (x ::~xs) = foldl f (f a x) xs;\\ |
28714 | 160 |
\hspace*{0pt}\\ |
34179 | 161 |
\hspace*{0pt}fun rev xs = foldl (fn xsa => fn x => x ::~xsa) [] xs;\\ |
28714 | 162 |
\hspace*{0pt}\\ |
34179 | 163 |
\hspace*{0pt}datatype 'a queue = AQueue of 'a list * 'a list;\\ |
28714 | 164 |
\hspace*{0pt}\\ |
34179 | 165 |
\hspace*{0pt}val empty :~'a queue = AQueue ([],~[]);\\ |
28714 | 166 |
\hspace*{0pt}\\ |
34179 | 167 |
\hspace*{0pt}fun dequeue (AQueue ([],~[])) = (NONE,~AQueue ([],~[]))\\ |
168 |
\hspace*{0pt} ~| dequeue (AQueue (xs,~y ::~ys)) = (SOME y,~AQueue (xs,~ys))\\ |
|
169 |
\hspace*{0pt} ~| dequeue (AQueue (v ::~va,~[])) =\\ |
|
28714 | 170 |
\hspace*{0pt} ~~~let\\ |
34179 | 171 |
\hspace*{0pt} ~~~~~val y ::~ys = rev (v ::~va);\\ |
28714 | 172 |
\hspace*{0pt} ~~~in\\ |
34179 | 173 |
\hspace*{0pt} ~~~~~(SOME y,~AQueue ([],~ys))\\ |
28714 | 174 |
\hspace*{0pt} ~~~end;\\ |
175 |
\hspace*{0pt}\\ |
|
34179 | 176 |
\hspace*{0pt}fun enqueue x (AQueue (xs,~ys)) = AQueue (x ::~xs,~ys);\\ |
28714 | 177 |
\hspace*{0pt}\\ |
29297 | 178 |
\hspace*{0pt}end;~(*struct Example*)% |
28447 | 179 |
\end{isamarkuptext}% |
180 |
\isamarkuptrue% |
|
181 |
% |
|
28564 | 182 |
\endisatagquote |
183 |
{\isafoldquote}% |
|
28447 | 184 |
% |
28564 | 185 |
\isadelimquote |
28447 | 186 |
% |
28564 | 187 |
\endisadelimquote |
28447 | 188 |
% |
189 |
\begin{isamarkuptext}% |
|
190 |
\noindent The \hyperlink{command.export-code}{\mbox{\isa{\isacommand{export{\isacharunderscore}code}}}} command takes a space-separated list of |
|
191 |
constants for which code shall be generated; anything else needed for those |
|
192 |
is added implicitly. Then follows a target language identifier |
|
193 |
(\isa{SML}, \isa{OCaml} or \isa{Haskell}) and a freely chosen module name. |
|
194 |
A file name denotes the destination to store the generated code. Note that |
|
195 |
the semantics of the destination depends on the target language: for |
|
196 |
\isa{SML} and \isa{OCaml} it denotes a \emph{file}, for \isa{Haskell} |
|
197 |
it denotes a \emph{directory} where a file named as the module name |
|
198 |
(with extension \isa{{\isachardot}hs}) is written:% |
|
199 |
\end{isamarkuptext}% |
|
200 |
\isamarkuptrue% |
|
201 |
% |
|
28564 | 202 |
\isadelimquote |
28447 | 203 |
% |
28564 | 204 |
\endisadelimquote |
28447 | 205 |
% |
28564 | 206 |
\isatagquote |
28447 | 207 |
\isacommand{export{\isacharunderscore}code}\isamarkupfalse% |
208 |
\ empty\ dequeue\ enqueue\ \isakeyword{in}\ Haskell\isanewline |
|
209 |
\ \ \isakeyword{module{\isacharunderscore}name}\ Example\ \isakeyword{file}\ {\isachardoublequoteopen}examples{\isacharslash}{\isachardoublequoteclose}% |
|
28564 | 210 |
\endisatagquote |
211 |
{\isafoldquote}% |
|
28447 | 212 |
% |
28564 | 213 |
\isadelimquote |
28447 | 214 |
% |
28564 | 215 |
\endisadelimquote |
28447 | 216 |
% |
217 |
\begin{isamarkuptext}% |
|
34155 | 218 |
\noindent This is the corresponding code in \isa{Haskell}:% |
28447 | 219 |
\end{isamarkuptext}% |
220 |
\isamarkuptrue% |
|
221 |
% |
|
28564 | 222 |
\isadelimquote |
28447 | 223 |
% |
28564 | 224 |
\endisadelimquote |
28447 | 225 |
% |
28564 | 226 |
\isatagquote |
28447 | 227 |
% |
228 |
\begin{isamarkuptext}% |
|
28727 | 229 |
\isatypewriter% |
28447 | 230 |
\noindent% |
28714 | 231 |
\hspace*{0pt}module Example where {\char123}\\ |
232 |
\hspace*{0pt}\\ |
|
29798 | 233 |
\hspace*{0pt}data Queue a = AQueue [a] [a];\\ |
28714 | 234 |
\hspace*{0pt}\\ |
29297 | 235 |
\hspace*{0pt}empty ::~forall a.~Queue a;\\ |
29798 | 236 |
\hspace*{0pt}empty = AQueue [] [];\\ |
28714 | 237 |
\hspace*{0pt}\\ |
29297 | 238 |
\hspace*{0pt}dequeue ::~forall a.~Queue a -> (Maybe a,~Queue a);\\ |
34179 | 239 |
\hspace*{0pt}dequeue (AQueue [] []) = (Nothing,~AQueue [] []);\\ |
240 |
\hspace*{0pt}dequeue (AQueue xs (y :~ys)) = (Just y,~AQueue xs ys);\\ |
|
241 |
\hspace*{0pt}dequeue (AQueue (v :~va) []) =\\ |
|
31848 | 242 |
\hspace*{0pt} ~let {\char123}\\ |
37610 | 243 |
\hspace*{0pt} ~~~(y :~ys) = reverse (v :~va);\\ |
31848 | 244 |
\hspace*{0pt} ~{\char125}~in (Just y,~AQueue [] ys);\\ |
28714 | 245 |
\hspace*{0pt}\\ |
29297 | 246 |
\hspace*{0pt}enqueue ::~forall a.~a -> Queue a -> Queue a;\\ |
34179 | 247 |
\hspace*{0pt}enqueue x (AQueue xs ys) = AQueue (x :~xs) ys;\\ |
28714 | 248 |
\hspace*{0pt}\\ |
249 |
\hspace*{0pt}{\char125}% |
|
28447 | 250 |
\end{isamarkuptext}% |
251 |
\isamarkuptrue% |
|
252 |
% |
|
28564 | 253 |
\endisatagquote |
254 |
{\isafoldquote}% |
|
28447 | 255 |
% |
28564 | 256 |
\isadelimquote |
28447 | 257 |
% |
28564 | 258 |
\endisadelimquote |
28447 | 259 |
% |
260 |
\begin{isamarkuptext}% |
|
261 |
\noindent This demonstrates the basic usage of the \hyperlink{command.export-code}{\mbox{\isa{\isacommand{export{\isacharunderscore}code}}}} command; |
|
262 |
for more details see \secref{sec:further}.% |
|
263 |
\end{isamarkuptext}% |
|
264 |
\isamarkuptrue% |
|
265 |
% |
|
38402 | 266 |
\isamarkupsubsection{If something utterly fails% |
267 |
} |
|
268 |
\isamarkuptrue% |
|
269 |
% |
|
270 |
\begin{isamarkuptext}% |
|
271 |
Under certain circumstances, the code generator fails to produce |
|
272 |
code entirely. |
|
273 |
||
274 |
\begin{description} |
|
275 |
||
276 |
\ditem{generate only one module} |
|
277 |
||
278 |
\ditem{check with a different target language} |
|
279 |
||
280 |
\ditem{inspect code equations} |
|
281 |
||
282 |
\ditem{inspect preprocessor setup} |
|
283 |
||
284 |
\ditem{generate exceptions} |
|
285 |
||
286 |
\ditem{remove offending code equations} |
|
287 |
||
288 |
\end{description}% |
|
289 |
\end{isamarkuptext}% |
|
290 |
\isamarkuptrue% |
|
291 |
% |
|
28447 | 292 |
\isamarkupsubsection{Code generator architecture \label{sec:concept}% |
293 |
} |
|
294 |
\isamarkuptrue% |
|
295 |
% |
|
296 |
\begin{isamarkuptext}% |
|
297 |
What you have seen so far should be already enough in a lot of cases. If you |
|
298 |
are content with this, you can quit reading here. Anyway, in order to customise |
|
34155 | 299 |
and adapt the code generator, it is necessary to gain some understanding |
28447 | 300 |
how it works. |
301 |
||
302 |
\begin{figure}[h] |
|
30882
d15725e84091
moved generated eps/pdf to main directory, for proper display in dvi;
wenzelm
parents:
30880
diff
changeset
|
303 |
\includegraphics{architecture} |
28447 | 304 |
\caption{Code generator architecture} |
305 |
\label{fig:arch} |
|
306 |
\end{figure} |
|
307 |
||
308 |
The code generator employs a notion of executability |
|
309 |
for three foundational executable ingredients known |
|
310 |
from functional programming: |
|
29560 | 311 |
\emph{code equations}, \emph{datatypes}, and |
312 |
\emph{type classes}. A code equation as a first approximation |
|
28447 | 313 |
is a theorem of the form \isa{f\ t\isactrlisub {\isadigit{1}}\ t\isactrlisub {\isadigit{2}}\ {\isasymdots}\ t\isactrlisub n\ {\isasymequiv}\ t} |
314 |
(an equation headed by a constant \isa{f} with arguments |
|
315 |
\isa{t\isactrlisub {\isadigit{1}}\ t\isactrlisub {\isadigit{2}}\ {\isasymdots}\ t\isactrlisub n} and right hand side \isa{t}). |
|
29560 | 316 |
Code generation aims to turn code equations |
28447 | 317 |
into a functional program. This is achieved by three major |
318 |
components which operate sequentially, i.e. the result of one is |
|
319 |
the input |
|
30880 | 320 |
of the next in the chain, see figure \ref{fig:arch}: |
28447 | 321 |
|
322 |
\begin{itemize} |
|
323 |
||
34155 | 324 |
\item The starting point is a collection of raw code equations in a |
325 |
theory. It is not relevant where they |
|
326 |
stem from, but typically they were either produced by specification |
|
327 |
tools or proved explicitly by the user. |
|
30836 | 328 |
|
34155 | 329 |
\item These raw code equations can be subjected to theorem transformations. This |
330 |
\qn{preprocessor} can apply the full |
|
30836 | 331 |
expressiveness of ML-based theorem transformations to code |
34155 | 332 |
generation. The result of preprocessing is a |
30836 | 333 |
structured collection of code equations. |
28447 | 334 |
|
30836 | 335 |
\item These code equations are \qn{translated} to a program in an |
336 |
abstract intermediate language. Think of it as a kind |
|
28447 | 337 |
of \qt{Mini-Haskell} with four \qn{statements}: \isa{data} |
29560 | 338 |
(for datatypes), \isa{fun} (stemming from code equations), |
28447 | 339 |
also \isa{class} and \isa{inst} (for type classes). |
340 |
||
341 |
\item Finally, the abstract program is \qn{serialised} into concrete |
|
342 |
source code of a target language. |
|
30836 | 343 |
This step only produces concrete syntax but does not change the |
344 |
program in essence; all conceptual transformations occur in the |
|
345 |
translation step. |
|
28447 | 346 |
|
347 |
\end{itemize} |
|
348 |
||
349 |
\noindent From these steps, only the two last are carried out outside the logic; by |
|
350 |
keeping this layer as thin as possible, the amount of code to trust is |
|
351 |
kept to a minimum.% |
|
352 |
\end{isamarkuptext}% |
|
353 |
\isamarkuptrue% |
|
354 |
% |
|
355 |
\isadelimtheory |
|
356 |
% |
|
357 |
\endisadelimtheory |
|
358 |
% |
|
359 |
\isatagtheory |
|
360 |
\isacommand{end}\isamarkupfalse% |
|
361 |
% |
|
362 |
\endisatagtheory |
|
363 |
{\isafoldtheory}% |
|
364 |
% |
|
365 |
\isadelimtheory |
|
366 |
% |
|
367 |
\endisadelimtheory |
|
368 |
\isanewline |
|
369 |
\end{isabellebody}% |
|
370 |
%%% Local Variables: |
|
371 |
%%% mode: latex |
|
372 |
%%% TeX-master: "root" |
|
373 |
%%% End: |