140 |> Symbol.source false |
151 |> Symbol.source false |
141 |> OuterLex.source false get_lexicon pos |
152 |> OuterLex.source false get_lexicon pos |
142 |> Source.source OuterLex.stopper (Scan.single scan) None |
153 |> Source.source OuterLex.stopper (Scan.single scan) None |
143 |> (fst o the o Source.get_single); |
154 |> (fst o the o Source.get_single); |
144 |
155 |
145 val check_header_lexicon = Scan.make_lexicon [Symbol.explode "theory"]; |
156 val check_header_lexicon = Scan.make_lexicon [Symbol.explode theoryN]; |
146 |
157 |
147 fun is_old_theory src = |
158 fun is_old_theory src = |
148 is_none (scan_header (K check_header_lexicon) (Scan.option (OuterParse.$$$ "theory")) src); |
159 is_none (scan_header (K check_header_lexicon) (Scan.option theory_keyword) src); |
149 |
160 |
150 fun warn_theory_style path is_old = |
161 fun warn_theory_style path is_old = |
151 let |
162 let |
152 val style = if is_old then "old" else "new"; |
163 val style = if is_old then "old" else "new"; |
153 val _ = warning ("Assuming " ^ style ^ "-style theory format for " ^ quote (Path.pack path)); |
164 val _ = warning ("Assuming " ^ style ^ "-style theory format for " ^ quote (Path.pack path)); |
154 in is_old end; |
165 in is_old end; |
155 |
166 |
156 |
167 |
157 (* deps_thy --- inspect theory header *) |
168 (* deps_thy --- inspect theory header *) |
158 |
169 |
159 val new_header_lexicon = |
170 val header_lexicon = |
160 Scan.make_lexicon (map Symbol.explode ["+", ":", "=", "files", "theory"]); |
171 Scan.make_lexicon (map Symbol.explode ["(", ")", "+", ":", "=", "files", theoryN]); |
161 |
172 |
162 local open OuterParse in |
173 local open OuterParse in |
163 |
174 |
164 val new_header = |
175 val file_name = ($$$ "(" |-- !!! (name --| $$$ ")")) >> rpair false || name >> rpair true; |
165 $$$ "theory" |-- !!! (name -- ($$$ "=" |-- enum1 "+" name) -- |
176 |
166 Scan.optional ($$$ "files" |-- !!! (Scan.repeat1 name)) [] --| (Scan.ahead eof || $$$ ":")); |
177 val theory_head = |
|
178 (name -- ($$$ "=" |-- enum1 "+" name) -- |
|
179 Scan.optional ($$$ "files" |-- !!! (Scan.repeat1 file_name)) []) |
|
180 >> (fn ((A, Bs), files) => (A, Bs, files)); |
|
181 |
|
182 val theory_header = theory_head --| (Scan.ahead eof || $$$ ":"); |
|
183 val only_header = theory_keyword |-- theory_head --| Scan.ahead eof; |
|
184 val new_header = theory_keyword |-- !!! theory_header; |
167 |
185 |
168 val old_header = |
186 val old_header = |
169 name -- ($$$ "=" |-- name -- Scan.repeat ($$$ "+" |-- name)) |
187 name -- ($$$ "=" |-- name -- Scan.repeat ($$$ "+" |-- name)) |
170 >> (fn (A, (B, Bs)) => ((A, B :: Bs), []: string list)); |
188 >> (fn (A, (B, Bs)) => (A, B :: Bs, []: (string * bool) list)); |
171 |
189 |
172 end; |
190 end; |
173 |
191 |
174 fun deps_thy name ml path = |
192 fun deps_thy name ml path = |
175 let |
193 let |
176 val src = Source.of_file path; |
194 val src = Source.of_file path; |
177 val is_old = warn_theory_style path (is_old_theory src); |
195 val is_old = warn_theory_style path (is_old_theory src); |
178 val ((name', parents), files) = |
196 val (name', parents, files) = |
179 (*Note: old style headers dynamically depend on the current lexicon :-( *) |
197 (*Note: old style headers dynamically depend on the current lexicon :-( *) |
180 if is_old then scan_header ThySyn.get_lexicon (Scan.error old_header) src |
198 if is_old then scan_header ThySyn.get_lexicon (Scan.error old_header) src |
181 else scan_header (K new_header_lexicon) (Scan.error new_header) src; |
199 else scan_header (K header_lexicon) (Scan.error new_header) src; |
182 |
200 |
183 val ml_path = ThyLoad.ml_path name; |
201 val ml_path = ThyLoad.ml_path name; |
184 val ml_file = if not ml orelse is_none (ThyLoad.check_file ml_path) then [] else [ml_path]; |
202 val ml_file = if not ml orelse is_none (ThyLoad.check_file ml_path) then [] else [ml_path]; |
185 in |
203 in |
186 if name <> name' then |
204 if name <> name' then |
187 error ("Filename " ^ quote (Path.pack path) ^ " does not match theory name " ^ quote name) |
205 error ("Filename " ^ quote (Path.pack path) ^ " does not match theory name " ^ quote name) |
188 else (parents, map Path.unpack files @ ml_file) |
206 else (parents, map (Path.unpack o #1) files @ ml_file) |
189 end; |
207 end; |
190 |
208 |
191 |
209 |
192 (* load_thy --- read text (including header) *) |
210 (* load_thy --- read text (including header) *) |
193 |
211 |
194 fun try_ml_file name ml = |
212 fun try_ml_file name ml time = |
195 let |
213 let |
196 val path = ThyLoad.ml_path name; |
214 val path = ThyLoad.ml_path name; |
197 val tr = Toplevel.imperative (fn () => ThyInfo.load_file path); |
215 val tr = Toplevel.imperative (fn () => ThyInfo.load_file time path); |
|
216 val tr_name = if time then "time_use" else "use"; |
198 in |
217 in |
199 if not ml orelse is_none (ThyLoad.check_file path) then () |
218 if not ml orelse is_none (ThyLoad.check_file path) then () |
200 else Toplevel.excursion [Toplevel.empty |> Toplevel.name "use" |> tr] |
219 else Toplevel.excursion [Toplevel.empty |> Toplevel.name tr_name |> tr] |
201 end; |
220 end; |
202 |
221 |
203 fun parse_thy (src, pos) = |
222 fun parse_thy (src, pos) = |
204 src |
223 let |
205 |> Symbol.source false |
224 val lex_src = |
206 |> OuterLex.source false (K (get_lexicon ())) pos |
225 src |
207 |> source false (K (get_parser ())) |
226 |> Symbol.source false |
208 |> Source.exhaust; |
227 |> OuterLex.source false (K (get_lexicon ())) pos; |
209 |
228 val only_head = |
210 fun read_thy name ml path = |
229 lex_src |
211 let |
230 |> Source.source OuterLex.stopper (Scan.single (Scan.option only_header)) None |
212 val (src, pos) = Source.of_file path; |
231 |> (fst o the o Source.get_single); |
213 val _ = |
232 in |
214 if is_old_theory (src, pos) then ThySyn.load_thy name (Source.exhaust src) |
233 (case only_head of |
215 else (Toplevel.excursion (parse_thy (src, pos)) |
234 None => |
216 handle exn => error (Toplevel.exn_message exn)); |
235 lex_src |
217 in Context.context (ThyInfo.get_theory name); try_ml_file name ml end; |
236 |> source false (K (get_parser ())) |
|
237 |> Source.exhaust |
|
238 | Some spec => |
|
239 [Toplevel.empty |> Toplevel.name theoryN |> IsarThy.theory spec, |
|
240 Toplevel.empty |> Toplevel.name "end" |> Toplevel.exit]) |
|
241 end; |
|
242 |
|
243 fun run_thy name path = |
|
244 let val (src, pos) = Source.of_file path in |
|
245 if is_old_theory (src, pos) then ThySyn.load_thy name (Source.exhaust src) |
|
246 else (Toplevel.excursion (parse_thy (src, pos)) |
|
247 handle exn => error (Toplevel.exn_message exn)) |
|
248 end; |
218 |
249 |
219 fun load_thy name ml time path = |
250 fun load_thy name ml time path = |
220 if not time then read_thy name ml path |
251 (if time then |
221 else timeit (fn () => |
252 timeit (fn () => |
222 (writeln ("\n**** Starting Theory " ^ quote name ^ " ****"); |
253 (writeln ("\n**** Starting theory " ^ quote name ^ " ****"); |
223 setmp Goals.proof_timing true (read_thy name ml) path; |
254 setmp Goals.proof_timing true (run_thy name) path; |
224 writeln ("**** Finished Theory " ^ quote name ^ " ****\n"))); |
255 writeln ("**** Finished theory " ^ quote name ^ " ****\n"))) |
|
256 else run_thy name path; |
|
257 Context.context (ThyInfo.get_theory name); |
|
258 try_ml_file name ml time); |
225 |
259 |
226 |
260 |
227 (* interactive source of state transformers *) |
261 (* interactive source of state transformers *) |
228 |
262 |
229 val isar = |
263 val isar = |