doc-src/Ref/syntax.tex
author paulson
Fri, 31 Jan 1997 17:13:19 +0100
changeset 2572 8a47f85e7a03
parent 1387 9bcad9c22fd4
child 3108 335efc3f5632
permissions -rw-r--r--
ex_impE was incorrectly listed as Safe
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     1
%% $Id$
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     2
\chapter{Syntax Transformations} \label{chap:syntax}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     3
\newcommand\ttapp{\mathrel{\hbox{\tt\$}}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     4
\newcommand\mtt[1]{\mbox{\tt #1}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     5
\newcommand\ttfct[1]{\mathop{\mtt{#1}}\nolimits}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     6
\newcommand\Constant{\ttfct{Constant}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     7
\newcommand\Variable{\ttfct{Variable}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     8
\newcommand\Appl[1]{\ttfct{Appl}\,[#1]}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
     9
\index{syntax!transformations|(}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    10
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    11
This chapter is intended for experienced Isabelle users who need to define
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    12
macros or code their own translation functions.  It describes the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    13
transformations between parse trees, abstract syntax trees and terms.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    14
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    15
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    16
\section{Abstract syntax trees} \label{sec:asts}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
    17
\index{ASTs|(}
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    18
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    19
The parser, given a token list from the lexer, applies productions to yield
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    20
a parse tree\index{parse trees}.  By applying some internal transformations
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    21
the parse tree becomes an abstract syntax tree, or \AST{}.  Macro
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    22
expansion, further translations and finally type inference yields a
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    23
well-typed term.  The printing process is the reverse, except for some
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    24
subtleties to be discussed later.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    25
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    26
Figure~\ref{fig:parse_print} outlines the parsing and printing process.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    27
Much of the complexity is due to the macro mechanism.  Using macros, you
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    28
can specify most forms of concrete syntax without writing any \ML{} code.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    29
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    30
\begin{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    31
\begin{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    32
\begin{tabular}{cl}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    33
string          & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    34
$\downarrow$    & parser \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    35
parse tree      & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    36
$\downarrow$    & parse \AST{} translation \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    37
\AST{}             & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    38
$\downarrow$    & \AST{} rewriting (macros) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    39
\AST{}             & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    40
$\downarrow$    & parse translation, type inference \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    41
--- well-typed term --- & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    42
$\downarrow$    & print translation \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    43
\AST{}             & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    44
$\downarrow$    & \AST{} rewriting (macros) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    45
\AST{}             & \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    46
$\downarrow$    & print \AST{} translation, printer \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    47
string          &
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    48
\end{tabular}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    49
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    50
\end{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    51
\caption{Parsing and printing}\label{fig:parse_print}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    52
\end{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    53
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    54
Abstract syntax trees are an intermediate form between the raw parse trees
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    55
and the typed $\lambda$-terms.  An \AST{} is either an atom (constant or
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    56
variable) or a list of {\em at least two\/} subtrees.  Internally, they
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    57
have type \mltydx{Syntax.ast}: \index{*Constant} \index{*Variable}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    58
\index{*Appl}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    59
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    60
datatype ast = Constant of string
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    61
             | Variable of string
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    62
             | Appl of ast list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    63
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    64
%
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    65
Isabelle uses an S-expression syntax for abstract syntax trees.  Constant
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    66
atoms are shown as quoted strings, variable atoms as non-quoted strings and
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
    67
applications as a parenthesised list of subtrees.  For example, the \AST
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    68
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    69
Appl [Constant "_constrain",
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    70
      Appl [Constant "_abs", Variable "x", Variable "t"],
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    71
      Appl [Constant "fun", Variable "'a", Variable "'b"]]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    72
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    73
is shown as {\tt ("_constrain" ("_abs" x t) ("fun" 'a 'b))}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    74
Both {\tt ()} and {\tt (f)} are illegal because they have too few
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
    75
subtrees.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    76
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    77
The resemblance to Lisp's S-expressions is intentional, but there are two
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    78
kinds of atomic symbols: $\Constant x$ and $\Variable x$.  Do not take the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    79
names {\tt Constant} and {\tt Variable} too literally; in the later
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    80
translation to terms, $\Variable x$ may become a constant, free or bound
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    81
variable, even a type constructor or class name; the actual outcome depends
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    82
on the context.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    83
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    84
Similarly, you can think of ${\tt (} f~x@1~\ldots~x@n{\tt )}$ as the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    85
application of~$f$ to the arguments $x@1, \ldots, x@n$.  But the kind of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    86
application is determined later by context; it could be a type constructor
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    87
applied to types.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    88
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    89
Forms like {\tt (("_abs" x $t$) $u$)} are legal, but \AST{}s are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    90
first-order: the {\tt "_abs"} does not bind the {\tt x} in any way.  Later
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    91
at the term level, {\tt ("_abs" x $t$)} will become an {\tt Abs} node and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    92
occurrences of {\tt x} in $t$ will be replaced by bound variables (the term
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    93
constructor \ttindex{Bound}).
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    94
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    95
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    96
\section{Transforming parse trees to \AST{}s}\label{sec:astofpt}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    97
\index{ASTs!made from parse trees}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    98
\newcommand\astofpt[1]{\lbrakk#1\rbrakk}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
    99
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   100
The parse tree is the raw output of the parser.  Translation functions,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   101
called {\bf parse AST translations}\indexbold{translations!parse AST},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   102
transform the parse tree into an abstract syntax tree.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   103
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   104
The parse tree is constructed by nesting the right-hand sides of the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   105
productions used to recognize the input.  Such parse trees are simply lists
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   106
of tokens and constituent parse trees, the latter representing the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   107
nonterminals of the productions.  Let us refer to the actual productions in
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   108
the form displayed by {\tt print_syntax} (see \S\ref{sec:inspct-thy} for an
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   109
example).
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   110
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   111
Ignoring parse \AST{} translations, parse trees are transformed to \AST{}s
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   112
by stripping out delimiters and copy productions.  More precisely, the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   113
mapping $\astofpt{-}$ is derived from the productions as follows:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   114
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   115
\item Name tokens: $\astofpt{t} = \Variable s$, where $t$ is an \ndx{id},
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   116
  \ndx{var}, \ndx{tid}, \ndx{tvar}, \ndx{xnum} or \ndx{xstr} token, and $s$
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   117
  its associated string. Note that for {\tt xstr} this does not include the
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   118
  quotes.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   119
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   120
\item Copy productions:\index{productions!copy}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   121
  $\astofpt{\ldots P \ldots} = \astofpt{P}$.  Here $\ldots$ stands for
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   122
  strings of delimiters, which are discarded.  $P$ stands for the single
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   123
  constituent that is not a delimiter; it is either a nonterminal symbol or
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   124
  a name token.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   125
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   126
  \item 0-ary productions: $\astofpt{\ldots \mtt{=>} c} = \Constant c$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   127
    Here there are no constituents other than delimiters, which are
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   128
    discarded.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   129
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   130
  \item $n$-ary productions, where $n \ge 1$: delimiters are discarded and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   131
    the remaining constituents $P@1$, \ldots, $P@n$ are built into an
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   132
    application whose head constant is~$c$:
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   133
    \[ \astofpt{\ldots P@1 \ldots P@n \ldots \mtt{=>} c} =
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   134
       \Appl{\Constant c, \astofpt{P@1}, \ldots, \astofpt{P@n}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   135
    \]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   136
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   137
Figure~\ref{fig:parse_ast} presents some simple examples, where {\tt ==},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   138
{\tt _appl}, {\tt _args}, and so forth name productions of the Pure syntax.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   139
These examples illustrate the need for further translations to make \AST{}s
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   140
closer to the typed $\lambda$-calculus.  The Pure syntax provides
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   141
predefined parse \AST{} translations\index{translations!parse AST} for
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   142
ordinary applications, type applications, nested abstractions, meta
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   143
implications and function types.  Figure~\ref{fig:parse_ast_tr} shows their
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   144
effect on some representative input strings.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   145
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   146
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   147
\begin{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   148
\begin{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   149
\tt\begin{tabular}{ll}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   150
\rm input string    & \rm \AST \\\hline
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   151
"f"                 & f \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   152
"'a"                & 'a \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   153
"t == u"            & ("==" t u) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   154
"f(x)"              & ("_appl" f x) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   155
"f(x, y)"           & ("_appl" f ("_args" x y)) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   156
"f(x, y, z)"        & ("_appl" f ("_args" x ("_args" y z))) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   157
"\%x y.\ t"         & ("_lambda" ("_idts" x y) t) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   158
\end{tabular}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   159
\end{center}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   160
\caption{Parsing examples using the Pure syntax}\label{fig:parse_ast}
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   161
\end{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   162
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   163
\begin{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   164
\begin{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   165
\tt\begin{tabular}{ll}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   166
\rm input string            & \rm \AST{} \\\hline
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   167
"f(x, y, z)"                & (f x y z) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   168
"'a ty"                     & (ty 'a) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   169
"('a, 'b) ty"               & (ty 'a 'b) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   170
"\%x y z.\ t"               & ("_abs" x ("_abs" y ("_abs" z t))) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   171
"\%x ::\ 'a.\ t"            & ("_abs" ("_constrain" x 'a) t) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   172
"[| P; Q; R |] => S"        & ("==>" P ("==>" Q ("==>" R S))) \\
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   173
"['a, 'b, 'c] => 'd"        & ("fun" 'a ("fun" 'b ("fun" 'c 'd)))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   174
\end{tabular}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   175
\end{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   176
\caption{Built-in parse \AST{} translations}\label{fig:parse_ast_tr}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   177
\end{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   178
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   179
The names of constant heads in the \AST{} control the translation process.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   180
The list of constants invoking parse \AST{} translations appears in the
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   181
output of {\tt print_syntax} under {\tt parse_ast_translation}.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   182
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   183
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   184
\section{Transforming \AST{}s to terms}\label{sec:termofast}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   185
\index{terms!made from ASTs}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   186
\newcommand\termofast[1]{\lbrakk#1\rbrakk}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   187
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   188
The \AST{}, after application of macros (see \S\ref{sec:macros}), is
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   189
transformed into a term.  This term is probably ill-typed since type
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   190
inference has not occurred yet.  The term may contain type constraints
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   191
consisting of applications with head {\tt "_constrain"}; the second
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   192
argument is a type encoded as a term.  Type inference later introduces
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   193
correct types or rejects the input.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   194
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   195
Another set of translation functions, namely parse
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   196
translations\index{translations!parse}, may affect this process.  If we
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   197
ignore parse translations for the time being, then \AST{}s are transformed
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   198
to terms by mapping \AST{} constants to constants, \AST{} variables to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   199
schematic or free variables and \AST{} applications to applications.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   200
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   201
More precisely, the mapping $\termofast{-}$ is defined by
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   202
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   203
\item Constants: $\termofast{\Constant x} = \ttfct{Const} (x,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   204
  \mtt{dummyT})$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   205
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   206
\item Schematic variables: $\termofast{\Variable \mtt{"?}xi\mtt"} =
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   207
  \ttfct{Var} ((x, i), \mtt{dummyT})$, where $x$ is the base name and $i$
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   208
  the index extracted from~$xi$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   209
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   210
\item Free variables: $\termofast{\Variable x} = \ttfct{Free} (x,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   211
  \mtt{dummyT})$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   212
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   213
\item Function applications with $n$ arguments:
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   214
    \[ \termofast{\Appl{f, x@1, \ldots, x@n}} =
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   215
       \termofast{f} \ttapp
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   216
         \termofast{x@1} \ttapp \ldots \ttapp \termofast{x@n}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   217
    \]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   218
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   219
Here \ttindex{Const}, \ttindex{Var}, \ttindex{Free} and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   220
\verb|$|\index{$@{\tt\$}} are constructors of the datatype \mltydx{term},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   221
while \ttindex{dummyT} stands for some dummy type that is ignored during
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   222
type inference.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   223
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   224
So far the outcome is still a first-order term.  Abstractions and bound
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   225
variables (constructors \ttindex{Abs} and \ttindex{Bound}) are introduced
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   226
by parse translations.  Such translations are attached to {\tt "_abs"},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   227
{\tt "!!"} and user-defined binders.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   228
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   229
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   230
\section{Printing of terms}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   231
\newcommand\astofterm[1]{\lbrakk#1\rbrakk}\index{ASTs!made from terms}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   232
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   233
The output phase is essentially the inverse of the input phase.  Terms are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   234
translated via abstract syntax trees into strings.  Finally the strings are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   235
pretty printed.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   236
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   237
Print translations (\S\ref{sec:tr_funs}) may affect the transformation of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   238
terms into \AST{}s.  Ignoring those, the transformation maps
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   239
term constants, variables and applications to the corresponding constructs
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   240
on \AST{}s.  Abstractions are mapped to applications of the special
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   241
constant {\tt _abs}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   242
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   243
More precisely, the mapping $\astofterm{-}$ is defined as follows:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   244
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   245
  \item $\astofterm{\ttfct{Const} (x, \tau)} = \Constant x$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   246
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   247
  \item $\astofterm{\ttfct{Free} (x, \tau)} = constrain (\Variable x,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   248
    \tau)$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   249
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   250
  \item $\astofterm{\ttfct{Var} ((x, i), \tau)} = constrain (\Variable
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   251
    \mtt{"?}xi\mtt", \tau)$, where $\mtt?xi$ is the string representation of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   252
    the {\tt indexname} $(x, i)$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   253
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   254
  \item For the abstraction $\lambda x::\tau.t$, let $x'$ be a variant
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   255
    of~$x$ renamed to differ from all names occurring in~$t$, and let $t'$
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   256
    be obtained from~$t$ by replacing all bound occurrences of~$x$ by
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   257
    the free variable $x'$.  This replaces corresponding occurrences of the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   258
    constructor \ttindex{Bound} by the term $\ttfct{Free} (x',
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   259
    \mtt{dummyT})$:
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   260
   \[ \astofterm{\ttfct{Abs} (x, \tau, t)} =
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   261
      \Appl{\Constant \mtt{"_abs"},
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   262
        constrain(\Variable x', \tau), \astofterm{t'}}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   263
    \]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   264
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   265
  \item $\astofterm{\ttfct{Bound} i} = \Variable \mtt{"B.}i\mtt"$.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   266
    The occurrence of constructor \ttindex{Bound} should never happen
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   267
    when printing well-typed terms; it indicates a de Bruijn index with no
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   268
    matching abstraction.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   269
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   270
  \item Where $f$ is not an application,
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   271
    \[ \astofterm{f \ttapp x@1 \ttapp \ldots \ttapp x@n} =
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   272
       \Appl{\astofterm{f}, \astofterm{x@1}, \ldots,\astofterm{x@n}}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   273
    \]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   274
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   275
%
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   276
Type constraints\index{type constraints} are inserted to allow the printing
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   277
of types.  This is governed by the boolean variable \ttindex{show_types}:
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   278
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   279
  \item $constrain(x, \tau) = x$ \ if $\tau = \mtt{dummyT}$ \index{*dummyT} or
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   280
    \ttindex{show_types} is set to {\tt false}.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   281
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   282
  \item $constrain(x, \tau) = \Appl{\Constant \mtt{"_constrain"}, x,
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   283
         \astofterm{\tau}}$ \ otherwise.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   284
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   285
    Here, $\astofterm{\tau}$ is the \AST{} encoding of $\tau$: type
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   286
    constructors go to {\tt Constant}s; type identifiers go to {\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   287
      Variable}s; type applications go to {\tt Appl}s with the type
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   288
    constructor as the first element.  If \ttindex{show_sorts} is set to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   289
    {\tt true}, some type variables are decorated with an \AST{} encoding
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   290
    of their sort.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   291
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   292
%
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   293
The \AST{}, after application of macros (see \S\ref{sec:macros}), is
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   294
transformed into the final output string.  The built-in {\bf print AST
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   295
  translations}\indexbold{translations!print AST} reverse the
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   296
parse \AST{} translations of Fig.\ts\ref{fig:parse_ast_tr}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   297
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   298
For the actual printing process, the names attached to productions
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   299
of the form $\ldots A^{(p@1)}@1 \ldots A^{(p@n)}@n \ldots \mtt{=>} c$ play
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   300
a vital role.  Each \AST{} with constant head $c$, namely $\mtt"c\mtt"$ or
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   301
$(\mtt"c\mtt"~ x@1 \ldots x@n)$, is printed according to the production
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   302
for~$c$.  Each argument~$x@i$ is converted to a string, and put in
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   303
parentheses if its priority~$(p@i)$ requires this.  The resulting strings
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   304
and their syntactic sugar (denoted by \dots{} above) are joined to make a
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   305
single string.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   306
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   307
If an application $(\mtt"c\mtt"~ x@1 \ldots x@m)$ has more arguments than the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   308
corresponding production, it is first split into $((\mtt"c\mtt"~ x@1 \ldots
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   309
x@n) ~ x@{n+1} \ldots x@m)$.  Applications with too few arguments or with
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   310
non-constant head or without a corresponding production are printed as
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   311
$f(x@1, \ldots, x@l)$ or $(\alpha@1, \ldots, \alpha@l) ty$.  An occurrence of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   312
$\Variable x$ is simply printed as~$x$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   313
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   314
Blanks are {\em not\/} inserted automatically.  If blanks are required to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   315
separate tokens, specify them in the mixfix declaration, possibly preceded
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   316
by a slash~({\tt/}) to allow a line break.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   317
\index{ASTs|)}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   318
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   319
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   320
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   321
\section{Macros: Syntactic rewriting} \label{sec:macros}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   322
\index{macros|(}\index{rewriting!syntactic|(}
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   324
Mixfix declarations alone can handle situations where there is a direct
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   325
connection between the concrete syntax and the underlying term.  Sometimes
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   326
we require a more elaborate concrete syntax, such as quantifiers and list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   327
notation.  Isabelle's {\bf macros} and {\bf translation functions} can
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   328
perform translations such as
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   329
\begin{center}\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   330
  \begin{tabular}{r@{$\quad\protect\rightleftharpoons\quad$}l}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   331
    ALL x:A.P   & Ball(A, \%x.P)        \\ \relax
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   332
    [x, y, z]   & Cons(x, Cons(y, Cons(z, Nil)))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   333
  \end{tabular}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   334
\end{center}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   335
Translation functions (see \S\ref{sec:tr_funs}) must be coded in ML; they
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   336
are the most powerful translation mechanism but are difficult to read or
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   337
write.  Macros are specified by first-order rewriting systems that operate
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   338
on abstract syntax trees.  They are usually easy to read and write, and can
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   339
express all but the most obscure translations.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   340
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   341
Figure~\ref{fig:set_trans} defines a fragment of first-order logic and set
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   342
theory.\footnote{This and the following theories are complete working
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   343
  examples, though they specify only syntax, no axioms.  The file {\tt
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   344
    ZF/ZF.thy} presents a full set theory definition, including many
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   345
  macro rules.}  Theory {\tt SET} defines constants for set comprehension
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   346
({\tt Collect}), replacement ({\tt Replace}) and bounded universal
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   347
quantification ({\tt Ball}).  Each of these binds some variables.  Without
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   348
additional syntax we should have to write $\forall x \in A.  P$ as {\tt
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   349
  Ball(A,\%x.P)}, and similarly for the others.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   350
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   351
\begin{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   352
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   353
SET = Pure +
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   354
types
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   355
  i o
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   356
arities
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   357
  i, o :: logic
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   358
consts
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   359
  Trueprop      :: o => prop                ("_" 5)
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   360
  Collect       :: [i, i => o] => i
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   361
  Replace       :: [i, [i, i] => o] => i
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   362
  Ball          :: [i, i => o] => o
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   363
syntax
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   364
  "{\at}Collect"    :: [idt, i, o] => i         ("(1{\ttlbrace}_:_./ _{\ttrbrace})")
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   365
  "{\at}Replace"    :: [idt, idt, i, o] => i    ("(1{\ttlbrace}_./ _:_, _{\ttrbrace})")
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   366
  "{\at}Ball"       :: [idt, i, o] => o         ("(3ALL _:_./ _)" 10)
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   367
translations
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   368
  "{\ttlbrace}x:A. P{\ttrbrace}"    == "Collect(A, \%x. P)"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   369
  "{\ttlbrace}y. x:A, Q{\ttrbrace}" == "Replace(A, \%x y. Q)"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   370
  "ALL x:A. P"  == "Ball(A, \%x. P)"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   371
end
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   372
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   373
\caption{Macro example: set theory}\label{fig:set_trans}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   374
\end{figure}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   375
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   376
The theory specifies a variable-binding syntax through additional productions
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   377
that have mixfix declarations.  Each non-copy production must specify some
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   378
constant, which is used for building \AST{}s. \index{constants!syntactic} The
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   379
additional constants are decorated with {\tt\at} to stress their purely
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   380
syntactic purpose; they may not occur within the final well-typed terms,
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   381
being declared as {\tt syntax} rather than {\tt consts}.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   382
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   383
The translations cause the replacement of external forms by internal forms
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   384
after parsing, and vice versa before printing of terms.  As a specification
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   385
of the set theory notation, they should be largely self-explanatory.  The
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   386
syntactic constants, {\tt\at Collect}, {\tt\at Replace} and {\tt\at Ball},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   387
appear implicitly in the macro rules via their mixfix forms.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   388
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   389
Macros can define variable-binding syntax because they operate on \AST{}s,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   390
which have no inbuilt notion of bound variable.  The macro variables {\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   391
  x} and~{\tt y} have type~{\tt idt} and therefore range over identifiers,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   392
in this case bound variables.  The macro variables {\tt P} and~{\tt Q}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   393
range over formulae containing bound variable occurrences.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   394
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   395
Other applications of the macro system can be less straightforward, and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   396
there are peculiarities.  The rest of this section will describe in detail
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   397
how Isabelle macros are preprocessed and applied.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   398
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   399
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   400
\subsection{Specifying macros}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   401
Macros are basically rewrite rules on \AST{}s.  But unlike other macro
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   402
systems found in programming languages, Isabelle's macros work in both
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   403
directions.  Therefore a syntax contains two lists of rewrites: one for
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   404
parsing and one for printing.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   405
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   406
\index{*translations section}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   407
The {\tt translations} section specifies macros.  The syntax for a macro is
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   408
\[ (root)\; string \quad
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   409
   \left\{\begin{array}[c]{c} \mtt{=>} \\ \mtt{<=} \\ \mtt{==} \end{array}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   410
   \right\} \quad
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   411
   (root)\; string
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   412
\]
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   413
%
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   414
This specifies a parse rule ({\tt =>}), a print rule ({\tt <=}), or both
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   415
({\tt ==}).  The two strings specify the left and right-hand sides of the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   416
macro rule.  The $(root)$ specification is optional; it specifies the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   417
nonterminal for parsing the $string$ and if omitted defaults to {\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   418
  logic}.  \AST{} rewrite rules $(l, r)$ must obey certain conditions:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   419
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   420
\item Rules must be left linear: $l$ must not contain repeated variables.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   421
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   422
\item Rules must have constant heads, namely $l = \mtt"c\mtt"$ or $l =
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   423
  (\mtt"c\mtt" ~ x@1 \ldots x@n)$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   424
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   425
\item Every variable in~$r$ must also occur in~$l$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   426
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   427
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   428
Macro rules may refer to any syntax from the parent theories.  They may
499
5a54c796b808 deleted repeated "the" in "before the the .thy file"
lcp
parents: 332
diff changeset
   429
also refer to anything defined before the {\tt .thy} file's {\tt
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   430
  translations} section --- including any mixfix declarations.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   431
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   432
Upon declaration, both sides of the macro rule undergo parsing and parse
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   433
\AST{} translations (see \S\ref{sec:asts}), but do not themselves undergo
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   434
macro expansion.  The lexer runs in a different mode that additionally
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   435
accepts identifiers of the form $\_~letter~quasiletter^*$ (like {\tt _idt},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   436
{\tt _K}).  Thus, a constant whose name starts with an underscore can
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   437
appear in macro rules but not in ordinary terms.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   438
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   439
Some atoms of the macro rule's \AST{} are designated as constants for
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   440
matching.  These are all names that have been declared as classes, types or
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   441
constants (logical and syntactic).
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   442
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   443
The result of this preprocessing is two lists of macro rules, each stored
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   444
as a pair of \AST{}s.  They can be viewed using {\tt print_syntax}
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   445
(sections \ttindex{parse_rules} and \ttindex{print_rules}).  For
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   446
theory~{\tt SET} of Fig.~\ref{fig:set_trans} these are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   447
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   448
parse_rules:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   449
  ("{\at}Collect" x A P)  ->  ("Collect" A ("_abs" x P))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   450
  ("{\at}Replace" y x A Q)  ->  ("Replace" A ("_abs" x ("_abs" y Q)))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   451
  ("{\at}Ball" x A P)  ->  ("Ball" A ("_abs" x P))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   452
print_rules:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   453
  ("Collect" A ("_abs" x P))  ->  ("{\at}Collect" x A P)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   454
  ("Replace" A ("_abs" x ("_abs" y Q)))  ->  ("{\at}Replace" y x A Q)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   455
  ("Ball" A ("_abs" x P))  ->  ("{\at}Ball" x A P)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   456
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   457
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   458
\begin{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   459
  Avoid choosing variable names that have previously been used as
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   460
  constants, types or type classes; the {\tt consts} section in the output
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   461
  of {\tt print_syntax} lists all such names.  If a macro rule works
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   462
  incorrectly, inspect its internal form as shown above, recalling that
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   463
  constants appear as quoted strings and variables without quotes.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   464
\end{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   465
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   466
\begin{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   467
If \ttindex{eta_contract} is set to {\tt true}, terms will be
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   468
$\eta$-contracted {\em before\/} the \AST{} rewriter sees them.  Thus some
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   469
abstraction nodes needed for print rules to match may vanish.  For example,
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   470
\verb|Ball(A, %x. P(x))| contracts to {\tt Ball(A, P)}; the print rule does
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   471
not apply and the output will be {\tt Ball(A, P)}.  This problem would not
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   472
occur if \ML{} translation functions were used instead of macros (as is
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   473
done for binder declarations).
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   474
\end{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   475
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   476
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   477
\begin{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   478
Another trap concerns type constraints.  If \ttindex{show_types} is set to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   479
{\tt true}, bound variables will be decorated by their meta types at the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   480
binding place (but not at occurrences in the body).  Matching with
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   481
\verb|Collect(A, %x. P)| binds {\tt x} to something like {\tt ("_constrain" y
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   482
"i")} rather than only {\tt y}.  \AST{} rewriting will cause the constraint to
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   483
appear in the external form, say \verb|{y::i:A::i. P::o}|.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   484
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   485
To allow such constraints to be re-read, your syntax should specify bound
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   486
variables using the nonterminal~\ndx{idt}.  This is the case in our
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   487
example.  Choosing {\tt id} instead of {\tt idt} is a common error,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   488
especially since it appears in former versions of most of Isabelle's
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   489
object-logics.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   490
\end{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   491
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   492
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   493
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   494
\subsection{Applying rules}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   495
As a term is being parsed or printed, an \AST{} is generated as an
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   496
intermediate form (recall Fig.\ts\ref{fig:parse_print}).  The \AST{} is
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   497
normalised by applying macro rules in the manner of a traditional term
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   498
rewriting system.  We first examine how a single rule is applied.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   499
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   500
Let $t$ be the abstract syntax tree to be normalised and $(l, r)$ some
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   501
translation rule.  A subtree~$u$ of $t$ is a {\bf redex} if it is an
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   502
instance of~$l$; in this case $l$ is said to {\bf match}~$u$.  A redex
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   503
matched by $l$ may be replaced by the corresponding instance of~$r$, thus
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   504
{\bf rewriting} the \AST~$t$.  Matching requires some notion of {\bf
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   505
  place-holders} that may occur in rule patterns but not in ordinary
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   506
\AST{}s; {\tt Variable} atoms serve this purpose.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   507
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   508
The matching of the object~$u$ by the pattern~$l$ is performed as follows:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   509
\begin{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   510
  \item Every constant matches itself.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   511
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   512
  \item $\Variable x$ in the object matches $\Constant x$ in the pattern.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   513
    This point is discussed further below.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   514
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   515
  \item Every \AST{} in the object matches $\Variable x$ in the pattern,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   516
    binding~$x$ to~$u$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   517
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   518
  \item One application matches another if they have the same number of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   519
    subtrees and corresponding subtrees match.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   520
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   521
  \item In every other case, matching fails.  In particular, {\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   522
      Constant}~$x$ can only match itself.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   523
\end{itemize}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   524
A successful match yields a substitution that is applied to~$r$, generating
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   525
the instance that replaces~$u$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   526
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   527
The second case above may look odd.  This is where {\tt Variable}s of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   528
non-rule \AST{}s behave like {\tt Constant}s.  Recall that \AST{}s are not
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   529
far removed from parse trees; at this level it is not yet known which
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   530
identifiers will become constants, bounds, frees, types or classes.  As
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   531
\S\ref{sec:asts} describes, former parse tree heads appear in \AST{}s as
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   532
{\tt Constant}s, while the name tokens \ndx{id}, \ndx{var}, \ndx{tid},
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   533
\ndx{tvar}, \ndx{xnum} and \ndx{xstr} become {\tt Variable}s.  On the other
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   534
hand, when \AST{}s generated from terms for printing, all constants and type
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   535
constructors become {\tt Constant}s; see \S\ref{sec:asts}.  Thus \AST{}s may
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   536
contain a messy mixture of {\tt Variable}s and {\tt Constant}s.  This is
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   537
insignificant at macro level because matching treats them alike.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   538
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   539
Because of this behaviour, different kinds of atoms with the same name are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   540
indistinguishable, which may make some rules prone to misbehaviour.  Example:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   541
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   542
types
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   543
  Nil
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   544
consts
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   545
  Nil     :: 'a list
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   546
syntax
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   547
  "[]"    :: 'a list    ("[]")
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   548
translations
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   549
  "[]"    == "Nil"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   550
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   551
The term {\tt Nil} will be printed as {\tt []}, just as expected.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   552
The term \verb|%Nil.t| will be printed as \verb|%[].t|, which might not be
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   553
expected!  Guess how type~{\tt Nil} is printed?
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   554
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   555
Normalizing an \AST{} involves repeatedly applying macro rules until none
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   556
are applicable.  Macro rules are chosen in the order that they appear in the
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   557
{\tt translations} section.  You can watch the normalization of \AST{}s
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   558
during parsing and printing by setting \ttindex{Syntax.trace_norm_ast} to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   559
{\tt true}.\index{tracing!of macros} Alternatively, use
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   560
\ttindex{Syntax.test_read}.  The information displayed when tracing
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   561
includes the \AST{} before normalization ({\tt pre}), redexes with results
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   562
({\tt rewrote}), the normal form finally reached ({\tt post}) and some
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   563
statistics ({\tt normalize}).  If tracing is off,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   564
\ttindex{Syntax.stat_norm_ast} can be set to {\tt true} in order to enable
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   565
printing of the normal form and statistics only.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   566
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   567
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   568
\subsection{Example: the syntax of finite sets}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   569
\index{examples!of macros}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   570
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   571
This example demonstrates the use of recursive macros to implement a
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   572
convenient notation for finite sets.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   573
\index{*empty constant}\index{*insert constant}\index{{}@\verb'{}' symbol}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   574
\index{"@Enum@{\tt\at Enum} constant}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   575
\index{"@Finset@{\tt\at Finset} constant}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   576
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   577
FINSET = SET +
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   578
types
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   579
  is
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   580
syntax
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   581
  ""            :: i => is                  ("_")
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   582
  "{\at}Enum"       :: [i, is] => is            ("_,/ _")
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   583
consts
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   584
  empty         :: i                        ("{\ttlbrace}{\ttrbrace}")
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   585
  insert        :: [i, i] => i
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   586
syntax
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   587
  "{\at}Finset"     :: is => i                  ("{\ttlbrace}(_){\ttrbrace}")
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   588
translations
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   589
  "{\ttlbrace}x, xs{\ttrbrace}"     == "insert(x, {\ttlbrace}xs{\ttrbrace})"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   590
  "{\ttlbrace}x{\ttrbrace}"         == "insert(x, {\ttlbrace}{\ttrbrace})"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   591
end
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   592
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   593
Finite sets are internally built up by {\tt empty} and {\tt insert}.  The
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   594
declarations above specify \verb|{x, y, z}| as the external representation
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   595
of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   596
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   597
insert(x, insert(y, insert(z, empty)))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   598
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   599
The nonterminal symbol~\ndx{is} stands for one or more objects of type~{\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   600
  i} separated by commas.  The mixfix declaration \hbox{\verb|"_,/ _"|}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   601
allows a line break after the comma for \rmindex{pretty printing}; if no
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   602
line break is required then a space is printed instead.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   603
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   604
The nonterminal is declared as the type~{\tt is}, but with no {\tt arities}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   605
declaration.  Hence {\tt is} is not a logical type and may be used safely as
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   606
a new nonterminal for custom syntax.  The nonterminal~{\tt is} can later be
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   607
re-used for other enumerations of type~{\tt i} like lists or tuples. If we
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   608
had needed polymorphic enumerations, we could have used the predefined
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   609
nonterminal symbol \ndx{args} and skipped this part altogether.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   610
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   611
\index{"@Finset@{\tt\at Finset} constant}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   612
Next follows {\tt empty}, which is already equipped with its syntax
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   613
\verb|{}|, and {\tt insert} without concrete syntax.  The syntactic
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   614
constant {\tt\at Finset} provides concrete syntax for enumerations of~{\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   615
  i} enclosed in curly braces.  Remember that a pair of parentheses, as in
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   616
\verb|"{(_)}"|, specifies a block of indentation for pretty printing.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   617
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   618
The translations may look strange at first.  Macro rules are best
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   619
understood in their internal forms:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   620
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   621
parse_rules:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   622
  ("{\at}Finset" ("{\at}Enum" x xs))  ->  ("insert" x ("{\at}Finset" xs))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   623
  ("{\at}Finset" x)  ->  ("insert" x "empty")
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   624
print_rules:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   625
  ("insert" x ("{\at}Finset" xs))  ->  ("{\at}Finset" ("{\at}Enum" x xs))
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   626
  ("insert" x "empty")  ->  ("{\at}Finset" x)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   627
\end{ttbox}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   628
This shows that \verb|{x,xs}| indeed matches any set enumeration of at least
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   629
two elements, binding the first to {\tt x} and the rest to {\tt xs}.
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   630
Likewise, \verb|{xs}| and \verb|{x}| represent any set enumeration.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   631
The parse rules only work in the order given.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   632
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   633
\begin{warn}
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   634
  The \AST{} rewriter cannot distinguish constants from variables and looks
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   635
  only for names of atoms.  Thus the names of {\tt Constant}s occurring in
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   636
  the (internal) left-hand side of translation rules should be regarded as
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   637
  \rmindex{reserved words}.  Choose non-identifiers like {\tt\at Finset} or
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   638
  sufficiently long and strange names.  If a bound variable's name gets
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   639
  rewritten, the result will be incorrect; for example, the term
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   640
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   641
\%empty insert. insert(x, empty)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   642
\end{ttbox}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   643
\par\noindent is incorrectly printed as \verb|%empty insert. {x}|.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   644
\end{warn}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   645
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   646
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   647
\subsection{Example: a parse macro for dependent types}\label{prod_trans}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   648
\index{examples!of macros}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   649
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   650
As stated earlier, a macro rule may not introduce new {\tt Variable}s on
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   651
the right-hand side.  Something like \verb|"K(B)" => "%x.B"| is illegal;
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   652
if allowed, it could cause variable capture.  In such cases you usually
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   653
must fall back on translation functions.  But a trick can make things
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   654
readable in some cases: {\em calling\/} translation functions by parse
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   655
macros:
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   656
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   657
PROD = FINSET +
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   658
consts
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   659
  Pi            :: [i, i => i] => i
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   660
syntax
1387
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   661
  "{\at}PROD"       :: [idt, i, i] => i       ("(3PROD _:_./ _)" 10)
9bcad9c22fd4 removed quotes from syntax and consts sections
clasohm
parents: 864
diff changeset
   662
  "{\at}->"         :: [i, i] => i            ("(_ ->/ _)" [51, 50] 50)
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   663
\ttbreak
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   664
translations
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   665
  "PROD x:A. B" => "Pi(A, \%x. B)"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   666
  "A -> B"      => "Pi(A, _K(B))"
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   667
end
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   668
ML
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   669
  val print_translation = [("Pi", dependent_tr' ("{\at}PROD", "{\at}->"))];
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   670
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   671
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   672
Here {\tt Pi} is a logical constant for constructing general products.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   673
Two external forms exist: the general case {\tt PROD x:A.B} and the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   674
function space {\tt A -> B}, which abbreviates \verb|Pi(A, %x.B)| when {\tt B}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   675
does not depend on~{\tt x}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   676
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   677
The second parse macro introduces {\tt _K(B)}, which later becomes
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   678
\verb|%x.B| due to a parse translation associated with \cdx{_K}.
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   679
Unfortunately there is no such trick for printing, so we have to add a {\tt
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   680
ML} section for the print translation \ttindex{dependent_tr'}.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   681
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   682
Recall that identifiers with a leading {\tt _} are allowed in translation
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   683
rules, but not in ordinary terms.  Thus we can create \AST{}s containing
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   684
names that are not directly expressible.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   685
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   686
The parse translation for {\tt _K} is already installed in Pure, and {\tt
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   687
dependent_tr'} is exported by the syntax module for public use.  See
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   688
\S\ref{sec:tr_funs} below for more of the arcane lore of translation functions.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   689
\index{macros|)}\index{rewriting!syntactic|)}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   690
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   691
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   692
\section{Translation functions} \label{sec:tr_funs}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   693
\index{translations|(}
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   694
%
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   695
This section describes the translation function mechanism.  By writing
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   696
\ML{} functions, you can do almost everything with terms or \AST{}s during
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   697
parsing and printing.  The logic \LK\ is a good example of sophisticated
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   698
transformations between internal and external representations of sequents;
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   699
here, macros would be useless.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   700
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   701
A full understanding of translations requires some familiarity
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   702
with Isabelle's internals, especially the datatypes {\tt term}, {\tt typ},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   703
{\tt Syntax.ast} and the encodings of types and terms as such at the various
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   704
stages of the parsing or printing process.  Most users should never need to
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   705
use translation functions.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   706
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   707
\subsection{Declaring translation functions}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   708
There are four kinds of translation functions.  Each such function is
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   709
associated with a name, which triggers calls to it.  Such names can be
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   710
constants (logical or syntactic) or type constructors.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   711
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   712
{\tt print_syntax} displays the sets of names associated with the
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   713
translation functions of a {\tt Syntax.syntax} under
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   714
\ttindex{parse_ast_translation}, \ttindex{parse_translation},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   715
\ttindex{print_translation} and \ttindex{print_ast_translation}.  You can
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   716
add new ones via the {\tt ML} section\index{*ML section} of
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   717
a {\tt .thy} file.  There may never be more than one function of the same
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   718
kind per name.  Even though the {\tt ML} section is the very last part of a
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   719
{\tt .thy} file, newly installed translation functions are effective when
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   720
processing the preceding section.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   721
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   722
The {\tt ML} section is copied verbatim near the beginning of the \ML\ file
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   723
generated from a {\tt .thy} file.  Definitions made here are accessible as
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   724
components of an \ML\ structure; to make some definitions private, use an
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   725
\ML{} {\tt local} declaration.  The {\tt ML} section may install translation
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   726
functions by declaring any of the following identifiers:
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   727
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   728
val parse_ast_translation : (string * (ast list -> ast)) list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   729
val print_ast_translation : (string * (ast list -> ast)) list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   730
val parse_translation     : (string * (term list -> term)) list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   731
val print_translation     : (string * (term list -> term)) list
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   732
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   733
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   734
\subsection{The translation strategy}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   735
All four kinds of translation functions are treated similarly.  They are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   736
called during the transformations between parse trees, \AST{}s and terms
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   737
(recall Fig.\ts\ref{fig:parse_print}).  Whenever a combination of the form
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   738
$(\mtt"c\mtt"~x@1 \ldots x@n)$ is encountered, and a translation function
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   739
$f$ of appropriate kind exists for $c$, the result is computed by the \ML{}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   740
function call $f \mtt[ x@1, \ldots, x@n \mtt]$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   741
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   742
For \AST{} translations, the arguments $x@1, \ldots, x@n$ are \AST{}s.  A
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   743
combination has the form $\Constant c$ or $\Appl{\Constant c, x@1, \ldots,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   744
  x@n}$.  For term translations, the arguments are terms and a combination
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   745
has the form $\ttfct{Const} (c, \tau)$ or $\ttfct{Const} (c, \tau) \ttapp
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   746
x@1 \ttapp \ldots \ttapp x@n$.  Terms allow more sophisticated
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   747
transformations than \AST{}s do, typically involving abstractions and bound
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   748
variables.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   749
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   750
Regardless of whether they act on terms or \AST{}s, parse translations differ
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   751
from print translations in their overall behaviour fundamentally:
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   752
\begin{description}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   753
\item[Parse translations] are applied bottom-up.  The arguments are already
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   754
  in translated form.  The translations must not fail; exceptions trigger
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   755
  an error message.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   756
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   757
\item[Print translations] are applied top-down.  They are supplied with
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   758
  arguments that are partly still in internal form.  The result again
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   759
  undergoes translation; therefore a print translation should not introduce
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   760
  as head the very constant that invoked it.  The function may raise
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   761
  exception \xdx{Match} to indicate failure; in this event it has no
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   762
  effect.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   763
\end{description}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   764
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   765
Only constant atoms --- constructor \ttindex{Constant} for \AST{}s and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   766
\ttindex{Const} for terms --- can invoke translation functions.  This
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   767
causes another difference between parsing and printing.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   768
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   769
Parsing starts with a string and the constants are not yet identified.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   770
Only parse tree heads create {\tt Constant}s in the resulting \AST, as
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   771
described in \S\ref{sec:astofpt}.  Macros and parse \AST{} translations may
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   772
introduce further {\tt Constant}s.  When the final \AST{} is converted to a
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   773
term, all {\tt Constant}s become {\tt Const}s, as described in
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   774
\S\ref{sec:termofast}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   775
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   776
Printing starts with a well-typed term and all the constants are known.  So
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   777
all logical constants and type constructors may invoke print translations.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   778
These, and macros, may introduce further constants.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   779
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   780
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   781
\subsection{Example: a print translation for dependent types}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   782
\index{examples!of translations}\indexbold{*dependent_tr'}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   783
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   784
Let us continue the dependent type example (page~\pageref{prod_trans}) by
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   785
examining the parse translation for~\cdx{_K} and the print translation
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   786
{\tt dependent_tr'}, which are both built-in.  By convention, parse
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   787
translations have names ending with {\tt _tr} and print translations have
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   788
names ending with {\tt _tr'}.  Search for such names in the Isabelle
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   789
sources to locate more examples.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   790
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   791
Here is the parse translation for {\tt _K}:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   792
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   793
fun k_tr [t] = Abs ("x", dummyT, incr_boundvars 1 t)
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   794
  | k_tr ts = raise TERM ("k_tr", ts);
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   795
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   796
If {\tt k_tr} is called with exactly one argument~$t$, it creates a new
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   797
{\tt Abs} node with a body derived from $t$.  Since terms given to parse
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   798
translations are not yet typed, the type of the bound variable in the new
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   799
{\tt Abs} is simply {\tt dummyT}.  The function increments all {\tt Bound}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   800
nodes referring to outer abstractions by calling \ttindex{incr_boundvars},
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   801
a basic term manipulation function defined in {\tt Pure/term.ML}.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   802
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   803
Here is the print translation for dependent types:
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   804
\begin{ttbox}
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   805
fun dependent_tr' (q, r) (A :: Abs (x, T, B) :: ts) =
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   806
      if 0 mem (loose_bnos B) then
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   807
        let val (x', B') = variant_abs (x, dummyT, B);
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   808
        in list_comb (Const (q, dummyT) $ Free (x', T) $ A $ B', ts)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   809
        end
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   810
      else list_comb (Const (r, dummyT) $ A $ B, ts)
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   811
  | dependent_tr' _ _ = raise Match;
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   812
\end{ttbox}
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   813
The argument {\tt (q,r)} is supplied to the curried function {\tt
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   814
  dependent_tr'} by a partial application during its installation.  We
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   815
can set up print translations for both {\tt Pi} and {\tt Sigma} by
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   816
including
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   817
\begin{ttbox}\index{*ML section}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   818
val print_translation =
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   819
  [("Pi",    dependent_tr' ("{\at}PROD", "{\at}->")),
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   820
   ("Sigma", dependent_tr' ("{\at}SUM", "{\at}*"))];
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   821
\end{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   822
within the {\tt ML} section.  The first of these transforms ${\tt Pi}(A,
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   823
\mtt{Abs}(x, T, B))$ into $\hbox{\tt{\at}PROD}(x', A, B')$ or
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   824
$\hbox{\tt{\at}->}(A, B)$, choosing the latter form if $B$ does not depend
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   825
on~$x$.  It checks this using \ttindex{loose_bnos}, yet another function
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   826
from {\tt Pure/term.ML}.  Note that $x'$ is a version of $x$ renamed away
332
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   827
from all names in $B$, and $B'$ is the body $B$ with {\tt Bound} nodes
01b87a921967 final Springer copy
lcp
parents: 323
diff changeset
   828
referring to the {\tt Abs} node replaced by $\ttfct{Free} (x',
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   829
\mtt{dummyT})$.
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   830
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   831
We must be careful with types here.  While types of {\tt Const}s are
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   832
ignored, type constraints may be printed for some {\tt Free}s and
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   833
{\tt Var}s if \ttindex{show_types} is set to {\tt true}.  Variables of type
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   834
\ttindex{dummyT} are never printed with constraint, though.  The line
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   835
\begin{ttbox}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   836
        let val (x', B') = variant_abs (x, dummyT, B);
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   837
\end{ttbox}\index{*variant_abs}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   838
replaces bound variable occurrences in~$B$ by the free variable $x'$ with
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   839
type {\tt dummyT}.  Only the binding occurrence of~$x'$ is given the
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   840
correct type~{\tt T}, so this is the only place where a type
864
d63b111b917a quite a lot of minor and major revisions (inspecting theories, read_axm,
wenzelm
parents: 499
diff changeset
   841
constraint might appear.
323
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   842
\index{translations|)}
361a71713176 penultimate Springer draft
lcp
parents:
diff changeset
   843
\index{syntax!transformations|)}