32
|
1 |
theory Ind_Interface
|
244
|
2 |
imports "../Base" Simple_Inductive_Package
|
32
|
3 |
begin
|
|
4 |
|
215
|
5 |
section {* Parsing and Typing the Specification\label{sec:interface} *}
|
124
|
6 |
|
219
|
7 |
text_raw {*
|
|
8 |
\begin{figure}[p]
|
|
9 |
\begin{boxedminipage}{\textwidth}
|
|
10 |
\begin{isabelle}
|
|
11 |
*}
|
|
12 |
simple_inductive
|
|
13 |
trcl :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool"
|
|
14 |
where
|
|
15 |
base: "trcl R x x"
|
|
16 |
| step: "trcl R x y \<Longrightarrow> R y z \<Longrightarrow> trcl R x z"
|
|
17 |
|
|
18 |
simple_inductive
|
|
19 |
even and odd
|
|
20 |
where
|
|
21 |
even0: "even 0"
|
|
22 |
| evenS: "odd n \<Longrightarrow> even (Suc n)"
|
|
23 |
| oddS: "even n \<Longrightarrow> odd (Suc n)"
|
|
24 |
|
|
25 |
simple_inductive
|
|
26 |
accpart :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> bool"
|
|
27 |
where
|
|
28 |
accpartI: "(\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
|
|
29 |
|
|
30 |
(*<*)
|
|
31 |
datatype trm =
|
|
32 |
Var "string"
|
|
33 |
| App "trm" "trm"
|
|
34 |
| Lam "string" "trm"
|
|
35 |
(*>*)
|
|
36 |
|
|
37 |
simple_inductive
|
|
38 |
fresh :: "string \<Rightarrow> trm \<Rightarrow> bool"
|
|
39 |
where
|
|
40 |
fresh_var: "a\<noteq>b \<Longrightarrow> fresh a (Var b)"
|
|
41 |
| fresh_app: "\<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
|
|
42 |
| fresh_lam1: "fresh a (Lam a t)"
|
|
43 |
| fresh_lam2: "\<lbrakk>a\<noteq>b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
|
|
44 |
text_raw {*
|
|
45 |
\end{isabelle}
|
|
46 |
\end{boxedminipage}
|
|
47 |
\caption{Specification given by the user for the inductive predicates
|
|
48 |
@{term "trcl"}, @{term "even"} and @{term "odd"}, @{term "accpart"} and
|
244
|
49 |
@{term "fresh"}.\label{fig:specs}}
|
219
|
50 |
\end{figure}
|
|
51 |
*}
|
|
52 |
|
|
53 |
text {*
|
|
54 |
\begin{figure}[p]
|
|
55 |
\begin{boxedminipage}{\textwidth}
|
|
56 |
\begin{isabelle}
|
|
57 |
\railnontermfont{\rmfamily\itshape}
|
|
58 |
\railterm{simpleinductive,where,for}
|
|
59 |
\railalias{simpleinductive}{\simpleinductive{}}
|
|
60 |
\railalias{where}{\isacommand{where}}
|
|
61 |
\railalias{for}{\isacommand{for}}
|
|
62 |
\begin{rail}
|
|
63 |
simpleinductive target?\\ fixes
|
|
64 |
(where (thmdecl? prop + '|'))?
|
|
65 |
;
|
|
66 |
\end{rail}
|
|
67 |
\end{isabelle}
|
|
68 |
\end{boxedminipage}
|
|
69 |
\caption{A railroad diagram describing the syntax of \simpleinductive{}.
|
|
70 |
The \emph{target} indicates an optional locale; the \emph{fixes} are an
|
|
71 |
\isacommand{and}-separated list of names for the inductive predicates (they
|
224
|
72 |
can also contain typing- and syntax annotations); \emph{prop} stands for a
|
219
|
73 |
introduction rule with an optional theorem declaration (\emph{thmdecl}).
|
|
74 |
\label{fig:railroad}}
|
|
75 |
\end{figure}
|
|
76 |
*}
|
|
77 |
|
124
|
78 |
text {*
|
224
|
79 |
To be able to write down the specifications or inductive predicates, we have
|
|
80 |
to introduce
|
129
|
81 |
a new command (see Section~\ref{sec:newcommand}). As the keyword for the
|
219
|
82 |
new command we chose \simpleinductive{}. Examples of specifications we expect
|
|
83 |
the user gives for the inductive predicates from the previous section are
|
224
|
84 |
shown in Figure~\ref{fig:specs}. The general syntax we will parse is specified
|
|
85 |
in the railroad diagram shown in Figure~\ref{fig:railroad}. This diagram more
|
|
86 |
or less translates directly into the parser:
|
219
|
87 |
*}
|
|
88 |
|
|
89 |
ML{*val spec_parser =
|
|
90 |
OuterParse.fixes --
|
|
91 |
Scan.optional
|
|
92 |
(OuterParse.$$$ "where" |--
|
|
93 |
OuterParse.!!!
|
|
94 |
(OuterParse.enum1 "|"
|
|
95 |
(SpecParse.opt_thm_name ":" -- OuterParse.prop))) []*}
|
|
96 |
|
|
97 |
text {*
|
224
|
98 |
which we explained in Section~\ref{sec:parsingspecs}. However, if you look
|
|
99 |
closely, there is no code for parsing the target given optionally after the
|
|
100 |
keyword. This is an ``advanced'' feature which we will inherit for ``free''
|
|
101 |
from the infrastructure on which we shall build the package. The target
|
|
102 |
stands for a locale and allows us to specify
|
127
|
103 |
*}
|
|
104 |
|
|
105 |
locale rel =
|
|
106 |
fixes R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
|
|
107 |
|
|
108 |
text {*
|
218
7ff7325e3b4e
started to adapt the rest of chapter 5 to the simplified version without parameters (they will be described in the extension section)
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
109 |
and then define the transitive closure and the accessible part of this
|
7ff7325e3b4e
started to adapt the rest of chapter 5 to the simplified version without parameters (they will be described in the extension section)
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
110 |
locale as follows:
|
116
|
111 |
*}
|
|
112 |
|
129
|
113 |
simple_inductive (in rel)
|
|
114 |
trcl'
|
116
|
115 |
where
|
127
|
116 |
base: "trcl' x x"
|
|
117 |
| step: "trcl' x y \<Longrightarrow> R y z \<Longrightarrow> trcl' x z"
|
116
|
118 |
|
129
|
119 |
simple_inductive (in rel)
|
|
120 |
accpart'
|
116
|
121 |
where
|
127
|
122 |
accpartI: "(\<And>y. R y x \<Longrightarrow> accpart' y) \<Longrightarrow> accpart' x"
|
244
|
123 |
(*<*)ML %no{*fun filtered_input str =
|
|
124 |
filter OuterLex.is_proper (OuterSyntax.scan Position.none str)
|
|
125 |
fun parse p input = Scan.finite OuterLex.stopper (Scan.error p) input*}(*>*)
|
116
|
126 |
text {*
|
224
|
127 |
Note that in these definitions the parameter @{text R}, standing for the
|
|
128 |
relation, is left implicit. For the moment we will ignore this kind
|
|
129 |
of implicit parameters and rely on the fact that the infrastructure will
|
|
130 |
deal with them. Later, however, we will come back to them.
|
|
131 |
|
|
132 |
If we feed into the parser the string that corresponds to our definition
|
|
133 |
of @{term even} and @{term odd}
|
120
|
134 |
|
|
135 |
@{ML_response [display,gray]
|
|
136 |
"let
|
|
137 |
val input = filtered_input
|
|
138 |
(\"even and odd \" ^
|
|
139 |
\"where \" ^
|
|
140 |
\" even0[intro]: \\\"even 0\\\" \" ^
|
|
141 |
\"| evenS[intro]: \\\"odd n \<Longrightarrow> even (Suc n)\\\" \" ^
|
|
142 |
\"| oddS[intro]: \\\"even n \<Longrightarrow> odd (Suc n)\\\"\")
|
|
143 |
in
|
|
144 |
parse spec_parser input
|
|
145 |
end"
|
186
371e4375c994
made the Ackermann function example safer and included suggestions from MW
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
146 |
"(([(even, NONE, NoSyn), (odd, NONE, NoSyn)],
|
120
|
147 |
[((even0,\<dots>), \"\\^E\\^Ftoken\\^Eeven 0\\^E\\^F\\^E\"),
|
|
148 |
((evenS,\<dots>), \"\\^E\\^Ftoken\\^Eodd n \<Longrightarrow> even (Suc n)\\^E\\^F\\^E\"),
|
|
149 |
((oddS,\<dots>), \"\\^E\\^Ftoken\\^Eeven n \<Longrightarrow> odd (Suc n)\\^E\\^F\\^E\")]), [])"}
|
219
|
150 |
|
224
|
151 |
then we get back the specifications of the predicates (with type and syntax annotations),
|
|
152 |
and specifications of the introduction rules. This is all the information we
|
219
|
153 |
need for calling the package and setting up the keyword. The latter is
|
245
53112deda119
Jasmin and Christian added examples for the pretty-printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
154 |
done in Lines 5 to 7 in the code below.\footnote{FIXME: Is there a way to state
|
53112deda119
Jasmin and Christian added examples for the pretty-printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
155 |
here @{text "simple_inductive"}?}
|
120
|
156 |
*}
|
245
53112deda119
Jasmin and Christian added examples for the pretty-printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
157 |
(*<*)ML %no{*fun add_inductive_cmd pred_specs rule_specs lthy = lthy
|
53112deda119
Jasmin and Christian added examples for the pretty-printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
158 |
fun add_inductive pred_specs rule_specs lthy = lthy*}(*>*)
|
224
|
159 |
ML_val %linenosgray{*val specification =
|
|
160 |
spec_parser >>
|
|
161 |
(fn (pred_specs, rule_specs) => add_inductive_cmd pred_specs rule_specs)
|
|
162 |
|
244
|
163 |
val _ = OuterSyntax.local_theory "simple_inductive2"
|
224
|
164 |
"definition of simple inductive predicates"
|
|
165 |
OuterKeyword.thy_decl specification*}
|
|
166 |
|
|
167 |
text {*
|
|
168 |
We call @{ML local_theory in OuterSyntax} with the kind-indicator
|
|
169 |
@{ML thy_decl in OuterKeyword} since the package does not need to open
|
|
170 |
up any proof (see Section~\ref{sec:newcommand}).
|
|
171 |
The auxiliary function @{text specification} in Lines 1 to 3
|
|
172 |
gathers the information from the parser to be processed further
|
|
173 |
by the function @{text "add_inductive_cmd"}, which we describe below.
|
|
174 |
|
|
175 |
Note that the predicates when they come out of the parser are just some
|
|
176 |
``naked'' strings: they have no type yet (even if we annotate them with
|
|
177 |
types) and they are also not defined constants yet (which the predicates
|
|
178 |
eventually will be). Also the introduction rules are just strings. What we have
|
|
179 |
to do first is to transform the parser's output into some internal
|
|
180 |
datastructures that can be processed further. For this we can use the
|
|
181 |
function @{ML read_spec in Specification}. This function takes some strings
|
|
182 |
(with possible typing annotations) and some rule specifications, and attempts
|
|
183 |
to find a typing according to the given type constraints given by the
|
|
184 |
user and the type constraints by the ``ambient'' theory. It returns
|
|
185 |
the type for the predicates and also returns typed terms for the
|
|
186 |
introduction rules. So at the heart of the function
|
|
187 |
@{text "add_inductive_cmd"} is a call to @{ML read_spec in Specification}.
|
|
188 |
*}
|
219
|
189 |
|
244
|
190 |
ML_val{*fun add_inductive_cmd pred_specs rule_specs lthy =
|
219
|
191 |
let
|
|
192 |
val ((pred_specs', rule_specs'), _) =
|
|
193 |
Specification.read_spec pred_specs rule_specs lthy
|
|
194 |
in
|
|
195 |
add_inductive pred_specs' rule_specs' lthy
|
224
|
196 |
end*}
|
53
0c3580c831a4
removed the @{ML ...} antiquotation in favour of @{ML_open ...x}
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
197 |
|
0c3580c831a4
removed the @{ML ...} antiquotation in favour of @{ML_open ...x}
Christian Urban <urbanc@in.tum.de>
diff
changeset
|
198 |
text {*
|
224
|
199 |
Once we have the input data as some internal datastructure, we call
|
244
|
200 |
the function @{text add_inductive}. This function does the heavy duty
|
224
|
201 |
lifting in the package: it generates definitions for the
|
|
202 |
predicates and derives from them corresponding induction principles and
|
|
203 |
introduction rules. The description of this function will span over
|
|
204 |
the next two sections.
|
127
|
205 |
*}
|
219
|
206 |
(*<*)end(*>*) |