1 (* Title: src/Tools/isac/BridgeJEdit/Calculation.thy
2 Author: Walther Neuper, JKU Linz
3 (c) due to copyright terms
5 Outer syntax for Isabelle/Isac. Compare src/Pure/Pure.thy
9 imports "~~/src/Tools/isac/MathEngine/MathEngine" "HOL-SPARK.SPARK"
11 "Example" :: thy_load ("str") and (* "spark_vc" :: thy_goal *)
12 "Problem" and (* root-problem + recursively in Solution *)
13 "Specification" "Model" "References" "Solution" and (* structure only *)
14 "Given" "Find" "Relate" "Where" and (* await input of term *)
15 "RTheory" (* await input of string; "R" distingues "Problem".."RProblem" *)
16 "RProblem" "RMethod" and (* await input of string list *)
17 "Tactic" (* optional for each step 0..end of calculation *)
21 ML_file "~~/test/HOL/SPARK/test-data.sml" (*..:*)ML \<open>g_c_d_siv_content\<close>
29 section \<open>code for spark_open: cp.to cp_spark_vcs.ML, cp_spark_vcs.ML\<close>
31 We minimally change code for Example, until all works.
33 The code is separated from Calculation.thy into files cp_spark_vcs.ML and cp_spark_commands.ML,
34 because text\<open>...\<close> and (*...*) for const_name>\<open>...\<close> etc and @ {thms ...} causes errors.
36 Thus for Test_Isac (**)ML_file "cp_spark_vcs.ML", ""(*cp_spark_commands.ML*), "HOL-SPARK.SPARK"
40 subsection \<open>cp. HOL/SPARK/Tools/spark_vcs.ML\<close>
43 (* Title: src/Tools/isac/BridgeJEdit/cp_spark_vcs.ML
44 Author: Walther Neuper, JKU Linz
45 (c) due to copyright terms
47 Preliminary code for developing Outer_Syntax.command..Example from spark_open as a model.
48 The original signatures from this subsection are:
50 signature SPARK_VCS_PARTIALLY =
52 val err_unfinished: unit -> 'a
53 val strip_number: string -> string * string
54 val name_ord: string * string -> order
55 structure VCtab: TABLE
56 structure VCs: THEORY_DATA
57 val to_lower: string -> string
58 val partition_opt: ('a -> 'b option) -> 'a list -> 'b list * 'a list
59 val dest_def: 'a * Fdl_Parser.fdl_rule -> ('a * (string * Fdl_Parser.expr)) option
60 val builtin: unit Symtab.table
61 val complex_expr: Fdl_Parser.expr -> bool
62 val complex_rule: Fdl_Parser.fdl_rule -> bool
63 val is_trivial_vc: 'a list * ('b * Fdl_Parser.expr) list -> bool
64 val rulenames: ((string * int) * 'a) list -> string
65 val is_pfun: Symtab.key -> bool
66 val fold_opt: ('a -> 'b -> 'b) -> 'a option -> 'b -> 'b
67 val fold_pair: ('a -> 'b -> 'c) -> ('d -> 'c -> 'e) -> 'a * 'd -> 'b -> 'e
68 val fold_expr: (string -> 'a -> 'a) -> (string -> 'a -> 'a) -> Fdl_Parser.expr -> 'a -> 'a
69 val add_expr_pfuns: 'a Fdl_Parser.tab -> Fdl_Parser.expr -> Symtab.key list -> Symtab.key list
70 val lookup_prfx: string -> 'a Symtab.table -> Symtab.key -> 'a option
71 val fold_vcs: ('a -> 'b -> 'b) -> ('c * 'd * 'a list * 'a list) VCtab.table -> 'b -> 'b
72 val pfuns_of_vcs: string -> 'a Fdl_Parser.tab -> 'b Symtab.table -> ('c * 'd * ('e * Fdl_Parser.expr) list * ('e * Fdl_Parser.expr) list) VCtab.table -> Symtab.key list
75 val get_type: theory -> string -> Symtab.key -> (typ * (string * string) list) option
76 val mk_type': theory -> string -> string -> typ * (string * string) list
77 val mk_type: theory -> string -> string -> typ
78 val check_no_assoc: theory -> string -> string -> unit
79 val define_overloaded: bstring * term -> Proof.context -> thm * local_theory
80 val add_enum_type: string -> string -> theory -> theory
81 val lcase_eq: string * string -> bool
82 val check_enum: string list -> (string * 'a) list -> string option
83 val strip_prfx: string -> string * string
84 val assoc_ty_err: theory -> typ -> string -> string -> 'a
85 val unprefix_pfun: string -> string -> string
86 val invert_map: (''a * ''a) list -> (''a * 'b) list -> (''a * 'b) list
87 val get_record_info: theory -> typ -> Record.info option
88 val add_type_def: string -> string * Fdl_Parser.fdl_type -> ((term * bstring) Symtab.table * Name.context) * theory -> ((term * bstring) Symtab.table * Name.context) * theory
89 val add_const: string -> bstring * string -> ((term * string) Symtab.table * Name.context) * theory -> term * (((term * string) Symtab.table * Name.context) * theory)
90 val mk_unop: string -> term -> term
91 val strip_underscores: string -> string
92 val strip_tilde: string -> string
93 val mangle_name: string -> string
94 val mk_variables: theory -> string -> string list -> string -> (term * string) Symtab.table * Name.context -> term list * ((term * string) Symtab.table * Name.context)
95 val find_field: (string * string) list -> string -> (string * 'a) list -> (string * 'a) option
96 val find_field': ''a -> (''a list * 'b) list -> 'b option
97 val mk_times: term * term -> term
98 val term_of_expr: theory -> string -> Fdl_Parser.fdl_type Fdl_Parser.tab -> (('a list * string) option * term) Symtab.table -> (term * string) Symtab.table * Name.context -> Fdl_Parser.expr -> term * string
99 val mk_rulename: string * int -> binding
102 Fdl_Parser.fdl_type Fdl_Parser.tab ->
103 (('a list * string) option * term) Symtab.table ->
104 string Fdl_Parser.tab -> (string * int) * (string * Fdl_Parser.expr) -> ((term * string) Symtab.table * Name.context) * theory -> (binding * thm) * (((term * string) Symtab.table * Name.context) * theory)
105 val add_expr_idents: Fdl_Parser.expr -> string list -> string list
109 'b Symtab.table -> (string -> bool) -> ((string * int) * (string * Fdl_Parser.expr)) list -> ((string * int) * (string * Fdl_Parser.expr)) list -> ((string * int) * (string * Fdl_Parser.expr)) list
110 val add_var: string -> string * string -> ((term * string) Symtab.table * Name.context) * theory -> (string * typ) * (((term * string) Symtab.table * Name.context) * theory)
113 ('a * 'b * ('c * Fdl_Parser.expr) list * ('c * Fdl_Parser.expr) list) VCtab.table ->
114 ((term * string) Symtab.table * Name.context) * theory -> (string * typ) list * (((term * string) Symtab.table * Name.context) * theory)
115 val term_of_rule: theory -> string -> Fdl_Parser.fdl_type Fdl_Parser.tab -> (('a list * string) option * term) Symtab.table -> (term * string) Symtab.table * Name.context -> Fdl_Parser.fdl_rule -> term
116 val pfun_type: theory -> string -> string list * string -> typ
117 val check_pfun_type: theory -> string -> string -> term -> (string list * string) option -> (string list * string) option -> unit
118 val upd_option: 'a option -> 'a option -> 'a option
119 val check_pfuns_types: theory -> string -> (string list * string) Fdl_Parser.tab -> ((string list * string) option * term) Symtab.table -> ((string list * string) option * term) Symtab.table
120 val pp_vcs: string -> (string * 'a) list -> Pretty.T
121 val pp_open_vcs: (string * 'a) list -> Pretty.T
122 val partition_vcs: ('a * 'b option * 'c * 'd) VCtab.table -> (VCtab.key * ('a * 'b * 'c * 'd)) list * (VCtab.key * ('a * 'c * 'd)) list
123 val print_open_vcs: (Pretty.T -> Pretty.T) -> ('a * 'b option * 'c * 'd) VCtab.table -> ('a * 'b option * 'c * 'd) VCtab.table
128 fun err_unfinished () = error "An unfinished SPARK environment is still open."
130 val strip_number = apply2 implode o chop_suffix Fdl_Lexer.is_digit o raw_explode;
132 val name_ord = prod_ord string_ord (option_ord int_ord) o
133 apply2 (strip_number ##> Int.fromString);
135 structure VCtab = Table(type key = string val ord = name_ord);
137 structure VCs = Theory_Data
139 (*/----------------------------- this is stored in thy --------------------------------\*)
140 type T = (*Pure/General/table.ML: 'a *)
141 {pfuns: ((string list * string) option * term) Symtab.table,
142 type_map: (typ * (string * string) list) Symtab.table,
144 {ctxt: Element.context_i list,
145 defs: (binding * thm) list,
146 types: Fdl_Parser.fdl_type Fdl_Parser.tab,
147 funs: (string list * string) Fdl_Parser.tab,
148 pfuns: ((string list * string) option * term) Symtab.table,
149 ids: (term * string) Symtab.table * Name.context,
151 vcs: (string * thm list option *
152 (string * Fdl_Parser.expr) list * (string * Fdl_Parser.expr) list) VCtab.table,
154 prefix: string} option}
155 (*\----------------------------- this is stored in thy --------------------------------/*)
156 val empty : T = {pfuns = Symtab.empty, type_map = Symtab.empty, env = NONE}
158 fun merge ({pfuns = pfuns1, type_map = type_map1, env = NONE},
159 {pfuns = pfuns2, type_map = type_map2, env = NONE}) =
160 {pfuns = Symtab.merge (eq_pair (op =) (op aconv)) (pfuns1, pfuns2),
161 type_map = Symtab.merge (op =) (type_map1, type_map2),
163 | merge _ = err_unfinished ()
168 val to_lower = raw_explode #> map Symbol.to_ascii_lower #> implode;
171 (** set up verification conditions **)
173 fun partition_opt f =
175 fun part ys zs [] = (rev ys, rev zs)
176 | part ys zs (x :: xs) = (case f x of
177 SOME y => part (y :: ys) zs xs
178 | NONE => part ys (x :: zs) xs)
181 fun dest_def (id, (Fdl_Parser.Substitution_Rule ([], Fdl_Parser.Ident s, rhs))) = SOME (id, (s, rhs))
185 val builtin = Symtab.make (map (rpair ())
186 ["->", "<->", "or", "and", "not", "=", "<>", "<", ">", "<=", ">=",
187 "+", "-", "*", "/", "div", "mod", "**"]);
189 fun complex_expr (Fdl_Parser.Number _) = false
190 | complex_expr (Fdl_Parser.Ident _) = false
191 | complex_expr (Fdl_Parser.Funct (s, es)) =
192 not (Symtab.defined builtin s) orelse exists complex_expr es
193 | complex_expr (Fdl_Parser.Quantifier (_, _, _, e)) = complex_expr e
194 | complex_expr _ = true;
196 fun complex_rule (Fdl_Parser.Inference_Rule (es, e)) =
197 complex_expr e orelse exists complex_expr es
198 | complex_rule (Fdl_Parser.Substitution_Rule (es, e, e')) =
199 complex_expr e orelse complex_expr e' orelse
200 exists complex_expr es;
202 fun is_trivial_vc ([], [(_, Fdl_Parser.Ident "true")]) = true
203 | is_trivial_vc _ = false;
206 fun rulenames rules = commas
207 (map (fn ((s, i), _) => s ^ "(" ^ string_of_int i ^ ")") rules);
211 Symtab.defined builtin orf
212 can (unprefix "fld_") orf can (unprefix "upf_") orf
213 can (unsuffix "__pos") orf can (unsuffix "__val") orf
214 equal "succ" orf equal "pred";
216 fun fold_opt f = the_default I o Option.map f;
217 fun fold_pair f g (x, y) = f x #> g y;
219 fun fold_expr f g (Fdl_Parser.Funct (s, es)) = f s #> fold (fold_expr f g) es
220 | fold_expr f g (Fdl_Parser.Ident s) = g s
221 | fold_expr f g (Fdl_Parser.Number _) = I
222 | fold_expr f g (Fdl_Parser.Quantifier (_, _, _, e)) = fold_expr f g e
223 | fold_expr f g (Fdl_Parser.Element (e, es)) =
224 fold_expr f g e #> fold (fold_expr f g) es
225 | fold_expr f g (Fdl_Parser.Update (e, es, e')) =
226 fold_expr f g e #> fold (fold_expr f g) es #> fold_expr f g e'
227 | fold_expr f g (Fdl_Parser.Record (_, flds)) = fold (fold_expr f g o snd) flds
228 | fold_expr f g (Fdl_Parser.Array (_, default, assocs)) =
229 fold_opt (fold_expr f g) default #>
231 (fold (fold (fold_pair
232 (fold_expr f g) (fold_opt (fold_expr f g)))))
233 (fold_expr f g)) assocs;
236 fun add_expr_pfuns funs = fold_expr
237 (fn s => if is_pfun s then I else insert (op =) s)
238 (fn s => if is_none (Fdl_Parser.lookup funs s) then I else insert (op =) s);
240 fun lookup_prfx "" tab s = Symtab.lookup tab s
241 | lookup_prfx prfx tab s = (case Symtab.lookup tab s of
242 NONE => Symtab.lookup tab (prfx ^ "__" ^ s)
246 VCtab.fold (fn (_, (_, _, ps, cs)) => fold f ps #> fold f cs) vcs;
248 fun pfuns_of_vcs prfx funs pfuns vcs =
249 fold_vcs (add_expr_pfuns funs o snd) vcs [] |>
250 filter (is_none o lookup_prfx prfx pfuns);
252 val booleanN = "boolean";
253 val integerN = "integer";
256 fun get_type thy prfx ty =
257 let val {type_map, ...} = VCs.get thy
258 in lookup_prfx prfx type_map ty end;
260 fun mk_type' _ _ "integer" = (HOLogic.intT, [])
261 | mk_type' _ _ "boolean" = (HOLogic.boolT, [])
262 | mk_type' thy prfx ty =
263 (case get_type thy prfx ty of
265 (Syntax.check_typ (Proof_Context.init_global thy)
266 (Type (Sign.full_name thy (Binding.name ty), [])),
270 fun mk_type thy prfx ty = fst (mk_type' thy prfx ty);
272 fun check_no_assoc thy prfx s = case get_type thy prfx s of
274 | SOME _ => error ("Cannot associate a type with " ^ s ^
275 "\nsince it is no record or enumeration type");
278 fun define_overloaded (def_name, eq) lthy =
280 val ((c, _), rhs) = eq |> Syntax.check_term lthy |>
281 Logic.dest_equals |>> dest_Free;
282 val ((_, (_, thm)), lthy') = Local_Theory.define
283 ((Binding.name c, NoSyn), ((Binding.name def_name, []), rhs)) lthy
284 val ctxt_thy = Proof_Context.init_global (Proof_Context.theory_of lthy');
285 val thm' = singleton (Proof_Context.export lthy' ctxt_thy) thm
286 in (thm', lthy') end;
288 (** generate properties of enumeration types **)
290 fun add_enum_type tyname tyname' thy =
292 val {case_name, ...} = the (BNF_LFP_Compat.get_info thy [BNF_LFP_Compat.Keep_Nesting] tyname');
293 val cs = map Const (the (BNF_LFP_Compat.get_constrs thy tyname'));
295 val T = Type (tyname', []);
296 val p = Const (\<^const_name>\<open>pos\<close>, T --> HOLogic.intT);
297 val v = Const (\<^const_name>\<open>val\<close>, HOLogic.intT --> T);
298 val card = Const (\<^const_name>\<open>card\<close>,
299 HOLogic.mk_setT T --> HOLogic.natT) $ HOLogic.mk_UNIV T;
301 fun mk_binrel_def s f = Logic.mk_equals
302 (Const (s, T --> T --> HOLogic.boolT),
303 Abs ("x", T, Abs ("y", T,
304 Const (s, HOLogic.intT --> HOLogic.intT --> HOLogic.boolT) $
305 (f $ Bound 1) $ (f $ Bound 0))));
307 val (((def1, def2), def3), lthy) = thy |>
309 Class.instantiation ([tyname'], [], \<^sort>\<open>spark_enum\<close>) |>
311 define_overloaded ("pos_" ^ tyname ^ "_def", Logic.mk_equals
313 list_comb (Const (case_name, replicate k HOLogic.intT @
314 [T] ---> HOLogic.intT),
315 map (HOLogic.mk_number HOLogic.intT) (0 upto k - 1)))) ||>>
317 define_overloaded ("less_eq_" ^ tyname ^ "_def",
318 mk_binrel_def \<^const_name>\<open>less_eq\<close> p) ||>>
319 define_overloaded ("less_" ^ tyname ^ "_def",
320 mk_binrel_def \<^const_name>\<open>less\<close> p);
322 val UNIV_eq = Goal.prove lthy [] []
323 (HOLogic.mk_Trueprop (HOLogic.mk_eq
324 (HOLogic.mk_UNIV T, HOLogic.mk_set T cs)))
325 (fn {context = ctxt, ...} =>
326 resolve_tac ctxt @{thms subset_antisym} 1 THEN
327 resolve_tac ctxt @{thms subsetI} 1 THEN
328 Old_Datatype_Aux.exh_tac ctxt (K (#exhaust (BNF_LFP_Compat.the_info
329 (Proof_Context.theory_of ctxt) [BNF_LFP_Compat.Keep_Nesting] tyname'))) 1 THEN
330 ALLGOALS (asm_full_simp_tac ctxt));
332 val finite_UNIV = Goal.prove lthy [] []
333 (HOLogic.mk_Trueprop (Const (\<^const_name>\<open>finite\<close>,
334 HOLogic.mk_setT T --> HOLogic.boolT) $ HOLogic.mk_UNIV T))
335 (fn {context = ctxt, ...} => simp_tac (ctxt addsimps [UNIV_eq]) 1);
337 val card_UNIV = Goal.prove lthy [] []
338 (HOLogic.mk_Trueprop (HOLogic.mk_eq
339 (card, HOLogic.mk_number HOLogic.natT k)))
340 (fn {context = ctxt, ...} => simp_tac (ctxt addsimps [UNIV_eq]) 1);
342 val range_pos = Goal.prove lthy [] []
343 (HOLogic.mk_Trueprop (HOLogic.mk_eq
344 (Const (\<^const_name>\<open>image\<close>, (T --> HOLogic.intT) -->
345 HOLogic.mk_setT T --> HOLogic.mk_setT HOLogic.intT) $
346 p $ HOLogic.mk_UNIV T,
347 Const (\<^const_name>\<open>atLeastLessThan\<close>, HOLogic.intT -->
348 HOLogic.intT --> HOLogic.mk_setT HOLogic.intT) $
349 HOLogic.mk_number HOLogic.intT 0 $
350 (\<^term>\<open>int\<close> $ card))))
351 (fn {context = ctxt, ...} =>
352 simp_tac (ctxt addsimps [card_UNIV]) 1 THEN
353 simp_tac (ctxt addsimps [UNIV_eq, def1]) 1 THEN
354 resolve_tac ctxt @{thms subset_antisym} 1 THEN
356 resolve_tac ctxt @{thms subsetI} 1 THEN
357 asm_full_simp_tac (ctxt addsimps @{thms interval_expand}
358 delsimps @{thms atLeastLessThan_iff}) 1);
361 Class.prove_instantiation_instance (fn ctxt =>
362 Class.intro_classes_tac ctxt [] THEN
363 resolve_tac ctxt [finite_UNIV] 1 THEN
364 resolve_tac ctxt [range_pos] 1 THEN
365 simp_tac (put_simpset HOL_basic_ss ctxt addsimps [def3]) 1 THEN
366 simp_tac (put_simpset HOL_basic_ss ctxt addsimps [def2]) 1) lthy;
368 val (pos_eqs, val_eqs) = split_list (map_index (fn (i, c) =>
370 val n = HOLogic.mk_number HOLogic.intT i;
371 val th = Goal.prove lthy' [] []
372 (HOLogic.mk_Trueprop (HOLogic.mk_eq (p $ c, n)))
373 (fn {context = ctxt, ...} => simp_tac (ctxt addsimps [def1]) 1);
374 val th' = Goal.prove lthy' [] []
375 (HOLogic.mk_Trueprop (HOLogic.mk_eq (v $ n, c)))
376 (fn {context = ctxt, ...} =>
377 resolve_tac ctxt [@{thm inj_pos} RS @{thm injD}] 1 THEN
378 simp_tac (ctxt addsimps [@{thm pos_val}, range_pos, card_UNIV, th]) 1)
379 in (th, th') end) cs);
381 val first_el = Goal.prove lthy' [] []
382 (HOLogic.mk_Trueprop (HOLogic.mk_eq
383 (Const (\<^const_name>\<open>first_el\<close>, T), hd cs)))
384 (fn {context = ctxt, ...} => simp_tac (ctxt addsimps [@{thm first_el_def}, hd val_eqs]) 1);
386 val last_el = Goal.prove lthy' [] []
387 (HOLogic.mk_Trueprop (HOLogic.mk_eq
388 (Const (\<^const_name>\<open>last_el\<close>, T), List.last cs)))
389 (fn {context = ctxt, ...} =>
390 simp_tac (ctxt addsimps [@{thm last_el_def}, List.last val_eqs, card_UNIV]) 1);
394 ((Binding.name (tyname ^ "_card"), @{attributes [simp]}), [card_UNIV]) ||>>
396 ((Binding.name (tyname ^ "_pos"), @{attributes [simp]}), pos_eqs) ||>>
398 ((Binding.name (tyname ^ "_val"), @{attributes [simp]}), val_eqs) ||>>
400 ((Binding.name (tyname ^ "_first_el"), @{attributes [simp]}), [first_el]) ||>>
402 ((Binding.name (tyname ^ "_last_el"), @{attributes [simp]}), [last_el]) |> snd |>
403 Local_Theory.exit_global
407 val lcase_eq = (op =) o apply2 (to_lower o Long_Name.base_name);
409 fun check_enum [] [] = NONE
410 | check_enum els [] = SOME ("has no element(s) " ^ commas els)
411 | check_enum [] cs = SOME ("has extra element(s) " ^
412 commas (map (Long_Name.base_name o fst) cs))
413 | check_enum (el :: els) ((cname, _) :: cs) =
414 if lcase_eq (el, cname) then check_enum els cs
415 else SOME ("either has no element " ^ el ^
416 " or it is at the wrong position");
420 fun strip ys [] = ("", implode ys)
421 | strip ys ("_" :: "_" :: xs) = (implode (rev xs), implode ys)
422 | strip ys (x :: xs) = strip (x :: ys) xs
423 in strip [] (rev (raw_explode s)) end;
425 fun assoc_ty_err thy T s msg =
426 error ("Type " ^ Syntax.string_of_typ_global thy T ^
427 " associated with SPARK type " ^ s ^ "\n" ^ msg);
429 fun check_enum [] [] = NONE
430 | check_enum els [] = SOME ("has no element(s) " ^ commas els)
431 | check_enum [] cs = SOME ("has extra element(s) " ^
432 commas (map (Long_Name.base_name o fst) cs))
433 | check_enum (el :: els) ((cname, _) :: cs) =
434 if lcase_eq (el, cname) then check_enum els cs
435 else SOME ("either has no element " ^ el ^
436 " or it is at the wrong position");
438 fun unprefix_pfun "" s = s
439 | unprefix_pfun prfx s =
440 let val (prfx', s') = strip_prfx s
441 in if prfx = prfx' then s' else s end;
443 fun invert_map [] = I
445 map (apfst (the o AList.lookup (op =) (map swap cmap)));
447 fun get_record_info thy T = (case Record.dest_recTs T of
448 [(tyname, [\<^typ>\<open>unit\<close>])] =>
449 Record.get_info thy (Long_Name.qualifier tyname)
454 fun add_type_def prfx (s, Fdl_Parser.Basic_Type ty) (ids, thy) =
455 (check_no_assoc thy prfx s;
457 Typedecl.abbrev_global (Binding.name s, [], NoSyn)
458 (mk_type thy prfx ty) thy |> snd))
460 | add_type_def prfx (s, Fdl_Parser.Enum_Type els) ((tab, ctxt), thy) =
462 val (thy', tyname) = (case get_type thy prfx s of
465 val tyb = Binding.name s;
466 val tyname = Sign.full_name thy tyb
469 BNF_LFP_Compat.add_datatype [BNF_LFP_Compat.Keep_Nesting]
471 map (fn s => (Binding.name s, [], NoSyn)) els)] |> snd |>
472 add_enum_type s tyname,
475 | SOME (T as Type (tyname, []), cmap) =>
476 (case BNF_LFP_Compat.get_constrs thy tyname of
477 NONE => assoc_ty_err thy T s "is not a datatype"
479 let val (prfx', _) = strip_prfx s
481 case check_enum (map (unprefix_pfun prfx') els)
482 (invert_map cmap cs) of
483 NONE => (thy, tyname)
484 | SOME msg => assoc_ty_err thy T s msg
486 | SOME (T, _) => assoc_ty_err thy T s "is not a datatype");
487 val cs = map Const (the (BNF_LFP_Compat.get_constrs thy' tyname));
489 ((fold (Symtab.update_new o apsnd (rpair s)) (els ~~ cs) tab,
490 fold Name.declare els ctxt),
494 | add_type_def prfx (s, Fdl_Parser.Array_Type (argtys, resty)) (ids, thy) =
495 (check_no_assoc thy prfx s;
497 Typedecl.abbrev_global (Binding.name s, [], NoSyn)
498 (foldr1 HOLogic.mk_prodT (map (mk_type thy prfx) argtys) -->
499 mk_type thy prfx resty) thy |> snd))
501 | add_type_def prfx (s, Fdl_Parser.Record_Type fldtys) (ids, thy) =
503 let val fldTs = maps (fn (flds, ty) =>
504 map (rpair (mk_type thy prfx ty)) flds) fldtys
505 in case get_type thy prfx s of
507 Record.add_record {overloaded = false} ([], Binding.name s) NONE
508 (map (fn (fld, T) => (Binding.name fld, T, NoSyn)) fldTs) thy
510 (case get_record_info thy rT of
511 NONE => assoc_ty_err thy rT s "is not a record type"
512 | SOME {fields, ...} =>
513 let val fields' = invert_map cmap fields
515 (case subtract (lcase_eq o apply2 fst) fldTs fields' of
517 | flds => assoc_ty_err thy rT s ("has extra field(s) " ^
518 commas (map (Long_Name.base_name o fst) flds));
520 case AList.lookup lcase_eq fields' fld of
521 NONE => assoc_ty_err thy rT s ("has no field " ^ fld)
522 | SOME U => T = U orelse assoc_ty_err thy rT s
524 fld ^ " whose type\n" ^
525 Syntax.string_of_typ_global thy U ^
526 "\ndoes not match declared type\n" ^
527 Syntax.string_of_typ_global thy T)) fldTs;
532 | add_type_def prfx (s, Fdl_Parser.Pending_Type) (ids, thy) =
534 case get_type thy prfx s of
536 | NONE => Typedecl.typedecl_global {final = true} (Binding.name s, [], NoSyn) thy |> snd);
538 fun add_type_def prfx (s, Fdl_Parser.Basic_Type ty) (ids, thy) =
539 (check_no_assoc thy prfx s;
541 Typedecl.abbrev_global (Binding.name s, [], NoSyn)
542 (mk_type thy prfx ty) thy |> snd))
544 | add_type_def prfx (s, Fdl_Parser.Enum_Type els) ((tab, ctxt), thy) =
546 val (thy', tyname) = (case get_type thy prfx s of
549 val tyb = Binding.name s;
550 val tyname = Sign.full_name thy tyb
553 BNF_LFP_Compat.add_datatype [BNF_LFP_Compat.Keep_Nesting]
555 map (fn s => (Binding.name s, [], NoSyn)) els)] |> snd |>
556 add_enum_type s tyname,
559 | SOME (T as Type (tyname, []), cmap) =>
560 (case BNF_LFP_Compat.get_constrs thy tyname of
561 NONE => assoc_ty_err thy T s "is not a datatype"
563 let val (prfx', _) = strip_prfx s
565 case check_enum (map (unprefix_pfun prfx') els)
566 (invert_map cmap cs) of
567 NONE => (thy, tyname)
568 | SOME msg => assoc_ty_err thy T s msg
570 | SOME (T, _) => assoc_ty_err thy T s "is not a datatype");
571 val cs = map Const (the (BNF_LFP_Compat.get_constrs thy' tyname));
573 ((fold (Symtab.update_new o apsnd (rpair s)) (els ~~ cs) tab,
574 fold Name.declare els ctxt),
578 | add_type_def prfx (s, Fdl_Parser.Array_Type (argtys, resty)) (ids, thy) =
579 (check_no_assoc thy prfx s;
581 Typedecl.abbrev_global (Binding.name s, [], NoSyn)
582 (foldr1 HOLogic.mk_prodT (map (mk_type thy prfx) argtys) -->
583 mk_type thy prfx resty) thy |> snd))
585 | add_type_def prfx (s, Fdl_Parser.Record_Type fldtys) (ids, thy) =
587 let val fldTs = maps (fn (flds, ty) =>
588 map (rpair (mk_type thy prfx ty)) flds) fldtys
589 in case get_type thy prfx s of
591 Record.add_record {overloaded = false} ([], Binding.name s) NONE
592 (map (fn (fld, T) => (Binding.name fld, T, NoSyn)) fldTs) thy
594 (case get_record_info thy rT of
595 NONE => assoc_ty_err thy rT s "is not a record type"
596 | SOME {fields, ...} =>
597 let val fields' = invert_map cmap fields
599 (case subtract (lcase_eq o apply2 fst) fldTs fields' of
601 | flds => assoc_ty_err thy rT s ("has extra field(s) " ^
602 commas (map (Long_Name.base_name o fst) flds));
604 case AList.lookup lcase_eq fields' fld of
605 NONE => assoc_ty_err thy rT s ("has no field " ^ fld)
606 | SOME U => T = U orelse assoc_ty_err thy rT s
608 fld ^ " whose type\n" ^
609 Syntax.string_of_typ_global thy U ^
610 "\ndoes not match declared type\n" ^
611 Syntax.string_of_typ_global thy T)) fldTs;
616 | add_type_def prfx (s, Fdl_Parser.Pending_Type) (ids, thy) =
618 case get_type thy prfx s of
620 | NONE => Typedecl.typedecl_global {final = true} (Binding.name s, [], NoSyn) thy |> snd);
622 fun add_const prfx (s, ty) ((tab, ctxt), thy) =
624 val T = mk_type thy prfx ty;
625 val b = Binding.name s;
626 val c = Const (Sign.full_name thy b, T)
629 ((Symtab.update (s, (c, ty)) tab, Name.declare s ctxt),
630 Sign.add_consts [(b, T, NoSyn)] thy))
634 let val T = fastype_of t
635 in Const (s, T --> T) $ t end;
637 fun strip_underscores s =
638 strip_underscores (unsuffix "_" s) handle Fail _ => s;
641 unsuffix "~" s ^ "_init" handle Fail _ => s;
643 val mangle_name = strip_underscores #> strip_tilde;
645 fun mk_variables thy prfx xs ty (tab, ctxt) =
647 val T = mk_type thy prfx ty;
648 val (ys, ctxt') = fold_map Name.variant (map mangle_name xs) ctxt;
649 val zs = map (Free o rpair T) ys;
650 in (zs, (fold (Symtab.update o apsnd (rpair ty)) (xs ~~ zs) tab, ctxt')) end;
652 fun find_field [] fname fields =
653 find_first (curry lcase_eq fname o fst) fields
654 | find_field cmap fname fields =
655 (case AList.lookup (op =) cmap fname of
657 | SOME fname' => SOME (fname', the (AList.lookup (op =) fields fname')));
659 fun find_field' fname = get_first (fn (flds, fldty) =>
660 if member (op =) flds fname then SOME fldty else NONE);
662 fun mk_times (t, u) =
664 val setT = fastype_of t;
665 val T = HOLogic.dest_setT setT;
666 val U = HOLogic.dest_setT (fastype_of u)
668 Const (\<^const_name>\<open>Sigma\<close>, setT --> (T --> HOLogic.mk_setT U) -->
669 HOLogic.mk_setT (HOLogic.mk_prodT (T, U))) $ t $ Abs ("", T, u)
673 fun term_of_expr thy prfx types pfuns =
675 fun tm_of vs (Fdl_Parser.Funct ("->", [e, e'])) =
676 (HOLogic.mk_imp (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
678 | tm_of vs (Fdl_Parser.Funct ("<->", [e, e'])) =
679 (HOLogic.mk_eq (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
681 | tm_of vs (Fdl_Parser.Funct ("or", [e, e'])) =
682 (HOLogic.mk_disj (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
684 | tm_of vs (Fdl_Parser.Funct ("and", [e, e'])) =
685 (HOLogic.mk_conj (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
687 | tm_of vs (Fdl_Parser.Funct ("not", [e])) =
688 (HOLogic.mk_not (fst (tm_of vs e)), booleanN)
690 | tm_of vs (Fdl_Parser.Funct ("=", [e, e'])) =
691 (HOLogic.mk_eq (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
693 | tm_of vs (Fdl_Parser.Funct ("<>", [e, e'])) = (HOLogic.mk_not
694 (HOLogic.mk_eq (fst (tm_of vs e), fst (tm_of vs e'))), booleanN)
696 | tm_of vs (Fdl_Parser.Funct ("<", [e, e'])) = (HOLogic.mk_binrel \<^const_name>\<open>less\<close>
697 (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
699 | tm_of vs (Fdl_Parser.Funct (">", [e, e'])) = (HOLogic.mk_binrel \<^const_name>\<open>less\<close>
700 (fst (tm_of vs e'), fst (tm_of vs e)), booleanN)
702 | tm_of vs (Fdl_Parser.Funct ("<=", [e, e'])) = (HOLogic.mk_binrel \<^const_name>\<open>less_eq\<close>
703 (fst (tm_of vs e), fst (tm_of vs e')), booleanN)
705 | tm_of vs (Fdl_Parser.Funct (">=", [e, e'])) = (HOLogic.mk_binrel \<^const_name>\<open>less_eq\<close>
706 (fst (tm_of vs e'), fst (tm_of vs e)), booleanN)
708 | tm_of vs (Fdl_Parser.Funct ("+", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>plus\<close>
709 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
711 | tm_of vs (Fdl_Parser.Funct ("-", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>minus\<close>
712 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
714 | tm_of vs (Fdl_Parser.Funct ("*", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>times\<close>
715 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
717 | tm_of vs (Fdl_Parser.Funct ("/", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>divide\<close>
718 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
720 | tm_of vs (Fdl_Parser.Funct ("div", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>sdiv\<close>
721 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
723 | tm_of vs (Fdl_Parser.Funct ("mod", [e, e'])) = (HOLogic.mk_binop \<^const_name>\<open>modulo\<close>
724 (fst (tm_of vs e), fst (tm_of vs e')), integerN)
726 | tm_of vs (Fdl_Parser.Funct ("-", [e])) =
727 (mk_unop \<^const_name>\<open>uminus\<close> (fst (tm_of vs e)), integerN)
729 | tm_of vs (Fdl_Parser.Funct ("**", [e, e'])) =
730 (Const (\<^const_name>\<open>power\<close>, HOLogic.intT --> HOLogic.natT -->
731 HOLogic.intT) $ fst (tm_of vs e) $
732 (\<^const>\<open>nat\<close> $ fst (tm_of vs e')), integerN)
734 | tm_of (tab, _) (Fdl_Parser.Ident s) =
735 (case Symtab.lookup tab s of
737 | NONE => (case lookup_prfx prfx pfuns s of
738 SOME (SOME ([], resty), t) => (t, resty)
739 | _ => error ("Undeclared identifier " ^ s)))
741 | tm_of _ (Fdl_Parser.Number i) = (HOLogic.mk_number HOLogic.intT i, integerN)
743 | tm_of vs (Fdl_Parser.Quantifier (s, xs, ty, e)) =
745 val (ys, vs') = mk_variables thy prfx xs ty vs;
747 "for_all" => HOLogic.mk_all
748 | "for_some" => HOLogic.mk_exists)
750 (fold_rev (fn Free (x, T) => fn t => q (x, T, t))
751 ys (fst (tm_of vs' e)),
755 | tm_of vs (Fdl_Parser.Funct (s, es)) =
757 (* record field selection *)
758 (case try (unprefix "fld_") s of
759 SOME fname => (case es of
762 val (t, rcdty) = tm_of vs e;
763 val (rT, cmap) = mk_type' thy prfx rcdty
764 in case (get_record_info thy rT, Fdl_Parser.lookup types rcdty) of
765 (SOME {fields, ...}, SOME (Fdl_Parser.Record_Type fldtys)) =>
766 (case (find_field cmap fname fields,
767 find_field' fname fldtys) of
768 (SOME (fname', fT), SOME fldty) =>
769 (Const (fname', rT --> fT) $ t, fldty)
770 | _ => error ("Record " ^ rcdty ^
771 " has no field named " ^ fname))
772 | _ => error (rcdty ^ " is not a record type")
774 | _ => error ("Function " ^ s ^ " expects one argument"))
777 (* record field update *)
778 (case try (unprefix "upf_") s of
779 SOME fname => (case es of
782 val (t, rcdty) = tm_of vs e;
783 val (rT, cmap) = mk_type' thy prfx rcdty;
784 val (u, fldty) = tm_of vs e';
785 val fT = mk_type thy prfx fldty
786 in case get_record_info thy rT of
787 SOME {fields, ...} =>
788 (case find_field cmap fname fields of
791 (Const (fname' ^ "_update",
792 (fT --> fT) --> rT --> rT) $
793 Abs ("x", fT, u) $ t,
795 else error ("Type\n" ^
796 Syntax.string_of_typ_global thy fT ^
797 "\ndoes not match type\n" ^
798 Syntax.string_of_typ_global thy fU ^
799 "\nof field " ^ fname)
800 | NONE => error ("Record " ^ rcdty ^
801 " has no field named " ^ fname))
802 | _ => error (rcdty ^ " is not a record type")
804 | _ => error ("Function " ^ s ^ " expects two arguments"))
807 (* enumeration type to integer *)
808 (case try (unsuffix "__pos") s of
809 SOME tyname => (case es of
810 [e] => (Const (\<^const_name>\<open>pos\<close>,
811 mk_type thy prfx tyname --> HOLogic.intT) $ fst (tm_of vs e),
813 | _ => error ("Function " ^ s ^ " expects one argument"))
816 (* integer to enumeration type *)
817 (case try (unsuffix "__val") s of
818 SOME tyname => (case es of
819 [e] => (Const (\<^const_name>\<open>val\<close>,
820 HOLogic.intT --> mk_type thy prfx tyname) $ fst (tm_of vs e),
822 | _ => error ("Function " ^ s ^ " expects one argument"))
825 (* successor / predecessor of enumeration type element *)
826 if s = "succ" orelse s = "pred" then (case es of
829 val (t, tyname) = tm_of vs e;
830 val T = mk_type thy prfx tyname
832 (if s = "succ" then \<^const_name>\<open>succ\<close>
833 else \<^const_name>\<open>pred\<close>, T --> T) $ t, tyname)
835 | _ => error ("Function " ^ s ^ " expects one argument"))
837 (* user-defined proof function *)
839 (case lookup_prfx prfx pfuns s of
840 SOME (SOME (_, resty), t) =>
841 (list_comb (t, map (fst o tm_of vs) es), resty)
842 | _ => error ("Undeclared proof function " ^ s))))))
844 | tm_of vs (Fdl_Parser.Element (e, es)) =
845 let val (t, ty) = tm_of vs e
846 in case Fdl_Parser.lookup types ty of
847 SOME (Fdl_Parser.Array_Type (_, elty)) =>
848 (t $ foldr1 HOLogic.mk_prod (map (fst o tm_of vs) es), elty)
849 | _ => error (ty ^ " is not an array type")
852 | tm_of vs (Fdl_Parser.Update (e, es, e')) =
853 let val (t, ty) = tm_of vs e
854 in case Fdl_Parser.lookup types ty of
855 SOME (Fdl_Parser.Array_Type (idxtys, elty)) =>
857 val T = foldr1 HOLogic.mk_prodT
858 (map (mk_type thy prfx) idxtys);
859 val U = mk_type thy prfx elty;
862 (Const (\<^const_name>\<open>fun_upd\<close>, fT --> T --> U --> fT) $
863 t $ foldr1 HOLogic.mk_prod (map (fst o tm_of vs) es) $
867 | _ => error (ty ^ " is not an array type")
870 | tm_of vs (Fdl_Parser.Record (s, flds)) =
872 val (T, cmap) = mk_type' thy prfx s;
873 val {extension = (ext_name, _), fields, ...} =
874 (case get_record_info thy T of
875 NONE => error (s ^ " is not a record type")
876 | SOME info => info);
877 val flds' = map (apsnd (tm_of vs)) flds;
878 val fnames = fields |> invert_map cmap |>
879 map (Long_Name.base_name o fst);
880 val fnames' = map fst flds;
881 val (fvals, ftys) = split_list (map (fn s' =>
882 case AList.lookup lcase_eq flds' s' of
883 SOME fval_ty => fval_ty
884 | NONE => error ("Field " ^ s' ^ " missing in record " ^ s))
886 val _ = (case subtract lcase_eq fnames fnames' of
888 | xs => error ("Extra field(s) " ^ commas xs ^
890 val _ = (case duplicates (op =) fnames' of
892 | xs => error ("Duplicate field(s) " ^ commas xs ^
897 map (mk_type thy prfx) ftys @ [HOLogic.unitT] ---> T),
898 fvals @ [HOLogic.unit]),
902 | tm_of vs (Fdl_Parser.Array (s, default, assocs)) =
903 (case Fdl_Parser.lookup types s of
904 SOME (Fdl_Parser.Array_Type (idxtys, elty)) =>
906 val Ts = map (mk_type thy prfx) idxtys;
907 val T = foldr1 HOLogic.mk_prodT Ts;
908 val U = mk_type thy prfx elty;
909 fun mk_idx' T (e, NONE) = HOLogic.mk_set T [fst (tm_of vs e)]
910 | mk_idx' T (e, SOME e') = Const (\<^const_name>\<open>atLeastAtMost\<close>,
911 T --> T --> HOLogic.mk_setT T) $
912 fst (tm_of vs e) $ fst (tm_of vs e');
914 if length Ts <> length idx then
915 error ("Arity mismatch in construction of array " ^ s)
916 else foldr1 mk_times (map2 mk_idx' Ts idx);
917 fun mk_upd (idxs, e) t =
918 if length idxs = 1 andalso forall (is_none o snd) (hd idxs)
920 Const (\<^const_name>\<open>fun_upd\<close>, (T --> U) -->
921 T --> U --> T --> U) $ t $
922 foldl1 HOLogic.mk_prod
923 (map (fst o tm_of vs o fst) (hd idxs)) $
926 Const (\<^const_name>\<open>fun_upds\<close>, (T --> U) -->
927 HOLogic.mk_setT T --> U --> T --> U) $ t $
928 foldl1 (HOLogic.mk_binop \<^const_name>\<open>sup\<close>)
934 SOME e => Abs ("x", T, fst (tm_of vs e))
935 | NONE => Const (\<^const_name>\<open>undefined\<close>, T --> U)),
938 | _ => error (s ^ " is not an array type"))
943 fun mk_rulename (s, i) = Binding.name (s ^ string_of_int i);
946 fun add_def prfx types pfuns consts (id, (s, e)) (ids as (tab, ctxt), thy) =
947 (case Fdl_Parser.lookup consts s of
950 val (t, ty') = term_of_expr thy prfx types pfuns ids e;
951 val T = mk_type thy prfx ty;
952 val T' = mk_type thy prfx ty';
953 val _ = T = T' orelse
954 error ("Declared type " ^ ty ^ " of " ^ s ^
955 "\ndoes not match type " ^ ty' ^ " in definition");
956 val id' = mk_rulename id;
957 val ((t', (_, th)), lthy') = Named_Target.theory_init thy
958 |> Specification.definition NONE [] []
959 ((id', []), HOLogic.mk_Trueprop (HOLogic.mk_eq (Free (s, T), t)));
961 Proof_Context.export_morphism lthy'
962 (Proof_Context.init_global (Proof_Context.theory_of lthy'));
964 ((id', Morphism.thm phi th),
965 ((Symtab.update (s, (Morphism.term phi t', ty)) tab, Name.declare s ctxt),
966 Local_Theory.exit_global lthy'))
968 | NONE => error ("Undeclared constant " ^ s));
972 val add_expr_idents = fold_expr (K I) (insert (op =));
974 (* sort definitions according to their dependency *)
975 fun sort_defs _ _ _ _ [] sdefs = rev sdefs
976 | sort_defs prfx funs pfuns consts defs sdefs =
977 (case find_first (fn (_, (_, e)) =>
978 forall (is_some o lookup_prfx prfx pfuns)
979 (add_expr_pfuns funs e []) andalso
981 member (fn (s, (_, (s', _))) => s = s') sdefs id orelse
983 (add_expr_idents e [])) defs of
984 SOME d => sort_defs prfx funs pfuns consts
985 (remove (op =) d defs) (d :: sdefs)
986 | NONE => error ("Bad definitions: " ^ rulenames defs));
988 fun add_var prfx (s, ty) (ids, thy) =
989 let val ([Free p], ids') = mk_variables thy prfx [s] ty ids
990 in (p, (ids', thy)) end;
992 fun add_init_vars prfx vcs (ids_thy as ((tab, _), _)) =
993 fold_map (add_var prfx)
995 (fn s => case try (unsuffix "~") s of
996 SOME s' => (case Symtab.lookup tab s' of
997 SOME (_, ty) => SOME (s, ty)
998 | NONE => error ("Undeclared identifier " ^ s'))
1000 (fold_vcs (add_expr_idents o snd) vcs []))
1003 fun term_of_rule thy prfx types pfuns ids rule =
1004 let val tm_of = fst o term_of_expr thy prfx types pfuns ids
1006 Fdl_Parser.Inference_Rule (es, e) => Logic.list_implies
1007 (map (HOLogic.mk_Trueprop o tm_of) es, HOLogic.mk_Trueprop (tm_of e))
1008 | Fdl_Parser.Substitution_Rule (es, e, e') => Logic.list_implies
1009 (map (HOLogic.mk_Trueprop o tm_of) es,
1010 HOLogic.mk_Trueprop (HOLogic.mk_eq (tm_of e, tm_of e')))
1014 fun pfun_type thy prfx (argtys, resty) =
1015 map (mk_type thy prfx) argtys ---> mk_type thy prfx resty;
1017 fun check_pfun_type thy prfx s t optty1 optty2 =
1019 val T = fastype_of t;
1021 let val U = pfun_type thy prfx ty
1025 Syntax.string_of_typ_global thy T ^
1027 Syntax.string_of_term_global thy t ^
1028 " associated with proof function " ^ s ^
1029 "\ndoes not match declared type\n" ^
1030 Syntax.string_of_typ_global thy U)
1032 in (Option.map check optty1; Option.map check optty2; ()) end;
1034 fun upd_option x y = if is_some x then x else y;
1036 fun check_pfuns_types thy prfx funs =
1037 Symtab.map (fn s => fn (optty, t) =>
1038 let val optty' = Fdl_Parser.lookup funs (unprefix_pfun prfx s)
1040 (check_pfun_type thy prfx s t optty optty';
1041 (NONE |> upd_option optty |> upd_option optty', t))
1047 fun pp_vcs msg vcs = Pretty.big_list msg (map (Pretty.str o fst) vcs);
1049 fun pp_open_vcs [] = Pretty.str "All verification conditions have been proved."
1050 | pp_open_vcs vcs = pp_vcs
1051 "The following verification conditions remain to be proved:" vcs;
1053 fun partition_vcs vcs = VCtab.fold_rev
1054 (fn (name, (trace, SOME thms, ps, cs)) =>
1055 apfst (cons (name, (trace, thms, ps, cs)))
1056 | (name, (trace, NONE, ps, cs)) =>
1057 apsnd (cons (name, (trace, ps, cs))))
1060 fun print_open_vcs f vcs =
1061 (Pretty.writeln (f (pp_open_vcs (snd (partition_vcs vcs)))); vcs);
1063 (* set_env: Element.context_i list -> (binding * thm) list -> fdl_type tab ->
1064 (string list * string) tab -> term * string) Symtab.table * Name.context ->
1065 (string * thm list option * (string * expr) list * (string * expr) list) VCtab.table ->
1066 Path.T -> string -> theory -> theory
1067 Context --vvvv is made Theory_Data by -------------------vvvvvvv, see.def. above *)
1068 fun set_env ctxt defs types funs ids vcs path prefix thy = VCs.map (fn
1069 {pfuns, type_map, env = NONE} =>
1071 type_map = type_map,
1073 {ctxt = ctxt, defs = defs, types = types, funs = funs,
1074 pfuns = check_pfuns_types thy prefix funs pfuns,
1075 ids = ids, proving = false, vcs = print_open_vcs I vcs, path = path,
1077 | _ => err_unfinished ()) thy;
1078 VCs.map: (VCs.T -> VCs.T) -> theory -> theory;
1080 signature THEORY_DATA =
1083 val get: theory -> T
1084 val put: T -> theory -> theory
1085 val map: (T -> T) -> theory -> theory (*..(VCs.T -> VCs.T)*)
1089 structure Refs_Data = Theory_Data
1091 type T = References.T
1092 val empty : T = References.empty
1094 fun merge (_, refs) = refs
1097 Refs_Data.empty; (*in Refs_Data defined workers are hidden*)
1098 Refs_Data.extend; (*in Refs_Data defined workers are hidden*)
1099 Refs_Data.merge; (*in Refs_Data defined workers are hidden*)
1101 Value or constructor (empty) has not been declared in structure Refs *)
1103 Refs_Data.get: theory -> Refs_Data.T; (*from signature THEORY_DATA*)
1104 Refs_Data.put: Refs_Data.T -> theory -> theory; (*from signature THEORY_DATA*)
1105 Refs_Data.map: (Refs_Data.T -> Refs_Data.T) -> theory -> theory; (*from signature THEORY_DATA*)
1107 structure OMod_Data = Theory_Data
1112 fun merge (_, o_model) = o_model
1115 structure Ctxt_Data = Theory_Data
1117 type T = Proof.context
1118 val empty : T = ContextC.empty
1120 fun merge (_, ctxt) = ctxt
1124 fun set_vcs _(*{types, vars, consts, funs} : Fdl_Parser.decls*)
1125 _(*rules, _*) _(*(_, ident), vcs*) header path opt_prfx thy =
1127 (*/----- keep running from spark_open \<open>greatest_common_divisor/g_c_d\<close> -----\*)
1128 val ({types, vars, consts, funs} : Fdl_Parser.decls) =
1129 snd (Fdl_Parser.parse_declarations Position.start g_c_d_fdl_content)
1130 val (rules, _) = Fdl_Parser.parse_rules Position.start g_c_d_rls_content
1131 val ((_, ident), vcs) =
1132 snd (Fdl_Parser.parse_vcs Fdl_Lexer.siv_header Position.start g_c_d_siv_content)
1133 (*------ new argument: ParseC.vcs = ParseC.formalise ----------------------*)
1134 val formalise = case header of xxx as
1135 [(["Traegerlaenge L", "Streckenlast q_0", "Biegelinie y", "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", "FunktionsVariable x", "GleichungsVariablen [c, c_2, c_3, c_4]", "AbleitungBiegelinie dy"],
1136 ("Biegelinie", ["Biegelinien"], ["IntegrierenUndKonstanteBestimmen2"]))] => hd xxx
1137 | _ => error "magic failed: handling file exp_Statics_Biegel_Timischl_7-70.str failed"
1138 (*\----- keep running from spark_open \<open>greatest_common_divisor/g_c_d\<close> -----/*)
1139 val (hdlPIDE, _, refs, o_model, var_type_ctxt) = Step_Specify.initialisePIDE formalise
1140 (* ^^^^^^^ goes to PIDE as "Problem hdlPIDE" *)
1143 if opt_prfx = "" then
1144 space_implode "__" (Long_Name.explode (Long_Name.qualifier ident))
1146 val prfx = to_lower prfx';
1147 val {pfuns, ...} = VCs.get thy; (*..thy*)
1148 val (defs, rules') = partition_opt dest_def rules;
1150 subtract (fn ((_, (s, _)), (s', _)) => s = s') defs (Fdl_Parser.items consts);
1151 (* ignore all complex rules in rls files *)
1152 val (rules'', other_rules) =
1153 List.partition (complex_rule o snd) rules';
1154 val _ = if null rules'' then ()
1155 else warning ("Ignoring rules: " ^ rulenames rules'');
1157 val vcs' = VCtab.make (maps (fn (tr, vcs) =>
1158 map (fn (s, (ps, cs)) => (s, (tr, NONE, ps, cs)))
1159 (filter_out (is_trivial_vc o snd) vcs)) vcs);
1161 val _ = (case filter_out (is_some o Fdl_Parser.lookup funs)
1162 (pfuns_of_vcs prfx funs pfuns vcs') of
1164 | fs => error ("Undeclared proof function(s) " ^ commas fs));
1166 val (((defs', vars''), ivars)(*->*),(*<-*) (ids, thy')) = (*..thy'*)
1168 Symtab.update ("false", (\<^term>\<open>False\<close>, booleanN)) |>
1169 Symtab.update ("true", (\<^term>\<open>True\<close>, booleanN)), (*..(defs', vars'')*)
1170 Name.context)(*->*),(*<-*) (*..ivars*)
1171 thy |> Sign.add_path (*..thy*)
1172 ((if prfx' = "" then "" else prfx' ^ "__") ^ Long_Name.base_name ident)) |>
1173 fold (add_type_def prfx) (Fdl_Parser.items types) |>
1174 fold (snd oo add_const prfx) consts' |> (fn ids_thy as ((tab, _), _) =>
1176 fold_map (add_def prfx types pfuns consts)
1177 (sort_defs prfx funs pfuns (Symtab.defined tab) defs []) ||>>
1178 fold_map (add_var prfx) (Fdl_Parser.items vars) ||>>
1179 add_init_vars prfx vcs'); (*..(ids, thy')*)
1182 [Element.Fixes (map (fn (s, T) =>
1183 (Binding.name s, SOME T, NoSyn)) (vars'' @ ivars)),
1184 Element.Assumes (map (fn (id, rl) =>
1185 ((mk_rulename id, []),
1186 [(term_of_rule thy' prfx types pfuns ids rl, [])])) (*..thy'*)
1188 Element.Notes ("", [((Binding.name "defns", []), map (rpair [] o single o snd) defs')])]
1191 set_env ctxt defs' types funs ids vcs' path prfx thy'
1192 |> Refs_Data.put refs
1193 |> OMod_Data.put o_model
1194 |> Ctxt_Data.put var_type_ctxt
1199 subsection \<open>cp. HOL/SPARK/Tools/fdl_lexer.ML\<close>
1202 type chars = (string * Position.T) list;
1203 val e_chars = []: (string * Position.T) list;
1205 type banner = string * string * string; val e_banner = ("b1", "b2", "b3")
1206 type date = string * string * string; val e_date = ("d1", "d2", "d3")
1207 type time = string * string * string * string option; val e_time = ("t1", "t2", "t3", SOME "t4")
1209 fun siv_header (_: chars) =
1210 ((e_banner, (e_date, e_time), (e_date, e_time), ("", "")), e_chars);
1214 subsection \<open>cp. HOL/SPARK/Tools/spark_commands.ML\<close>
1217 (* Title: src/Tools/isac/BridgeJEdit/cp_spark_commands.ML
1218 Author: Walther Neuper, JKU Linz
1219 (c) due to copyright terms
1221 Preliminary code for developing Outer_Syntax.command..Example from spark_open as a model.
1224 fun spark_open header (files, prfx) thy =
1225 (*Fdl_Lexer.siv_header*)
1227 (** )val _ = @{print} {a = "//--- ###C spark_open", files = files, prfx = prfx};( **)
1228 val xxx as ([{src_path, lines = vc_lines, pos = vc_pos, ...}: Token.file (*,.siv*)
1229 (** ) {lines = fdl_lines, pos = fdl_pos, ...}, ( *.fld*)
1230 (** ) {lines = rls_lines, pos = rls_pos, ...} ( *.rls*)
1232 ((** @{print} {a = "###C spark_open: before call <files thy>, files = siv_header !"};( **)
1235 val path = fst (Path.split_ext src_path);
1237 (** )@{print} {a = "###C spark_open: result from siv_header, without thy'", fst_xxx = fst xxx};( **)
1238 (** )@{print} {a = "###C spark_open: 1 arg for SPARK_VCs.set_vcs",
1239 (** ) arg1 = (snd (Fdl_Parser.parse_declarations fdl_pos (cat_lines fdl_lines))),
1240 arg2 = (Fdl_Parser.parse_rules rls_pos (cat_lines rls_lines)), ( **)
1241 (** ) arg3 = (snd (Fdl_Parser.parse_vcs header vc_pos (cat_lines vc_lines))), ( **)
1243 z = "\\--- ###C spark_open"};( **)
1244 (*SPARK_VCs.*)set_vcs
1246 (** ) (snd (Fdl_Parser.parse_declarations fdl_pos (cat_lines fdl_lines)))( **)Fdl_Parser.empty_decls(**)
1247 (** ) (Fdl_Parser.parse_rules rls_pos (cat_lines rls_lines)) ( **)Fdl_Parser.empty_rules(**)
1248 (** ) (snd (Fdl_Parser.parse_vcs header vc_pos (cat_lines vc_lines))) ( **)Fdl_Parser.empty_vcs(**)
1249 (**) (ParseC.read_out_formalise (fst (header (fst (ParseC.scan' vc_pos (cat_lines vc_lines))))))(**)
1253 \<close> ML \<open> (* compose NEW argument "header" ^v^v^v^v^v^v^v^v^v^v^v^v^v^v*)
1254 (ParseC.read_out_formalise (fst (ParseC.vcs (fst (ParseC.scan' Position.start formalise_str)))))
1257 \<close> ML \<open> (* generate the arguments directly for: spark_open \<open>greatest_common_divisor/g_c_d\<close>*)
1258 (* (snd (Fdl_Parser.parse_declarations fdl_pos (cat_lines fdl_lines))) *)
1259 snd (Fdl_Parser.parse_declarations Position.start g_c_d_fdl_content)
1261 (* (Fdl_Parser.parse_rules rls_pos (cat_lines rls_lines)) *)
1262 Fdl_Parser.parse_rules Position.start g_c_d_rls_content
1264 val (("procedure", "Greatest_Common_Divisor.G_C_D"), vcs) =
1265 (* (snd (Fdl_Parser.parse_vcs header vc_pos (cat_lines vc_lines))) *)
1266 snd (Fdl_Parser.parse_vcs Fdl_Lexer.siv_header Position.start g_c_d_siv_content);
1273 section \<open>setup command_keyword \<close>
1274 subsection \<open>hide for development, use for Test_Isac\<close>
1276 (*HIDE for development, activate for Test_Isac*)
1277 type chars = (string * Position.T) list;
1278 val e_chars = []: (string * Position.T) list;
1280 fun spark_open (_: ((*Fdl_Lexer.*)chars -> 'a * (*Fdl_Lexer.*)chars))
1281 (_: ('b -> Token.file list * theory) * string) (_: 'b) = @ {theory}
1283 type banner = string * string * string; val e_banner = ("b1", "b2", "b3")
1284 type date = string * string * string; val e_date = ("d1", "d2", "d3")
1285 type time = string * string * string * string option; val e_time = ("t1", "t2", "t3", SOME "t4")
1287 fun siv_header (_: chars) =
1288 ((e_banner, (e_date, e_time), (e_date, e_time), ("", "")), e_chars);
1289 (*HIDE for development, activate for Test_Isac*)
1292 subsection \<open>def.for Build_Isac; for Test_Isac outcomment SPARK_Commands, Fdl_Lexer below\<close>
1295 val siv_header = ParseC.vcs; (*---------------------------------------------vvvvvvvvv*)
1298 Outer_Syntax.command \<^command_keyword>\<open>Example\<close> "start Isac Calculation from a Formalise-file"
1299 (Resources.provide_parse_files "spark_open" -- Parse.parname
1300 >> (Toplevel.theory o ((*SPARK_Commands.*)spark_open (*Fdl_Lexer.( **)siv_header)));
1301 (*--------------------------------------------------------------------------^^^^^^^^^^*)
1306 subsection \<open>test runs with Example and spark_open\<close>
1307 (*======= vv-- Example =================================================================*)
1308 (** Test_Isac finds exp_Statics_Biegel_Timischl_7-70.siv ?!?* )
1309 Example \<open>/usr/local/isabisac/src/Tools/isac/Examples/exp_Statics_Biegel_Timischl_7-70\<close>(*.str*)
1313 (*====== ^^-- Example, spark_open--vv ==================================================*)
1314 (* DO THAT IN ..................... HOL/SPARK/Examples/Gcd/Greatest_Common_Divisor.thy)
1315 spark_open \<open>/usr/local/isabisac/src/HOL/SPARK/Examples/Gcd/greatest_common_divisor/g_c_d\<close>
1319 (*==================== spark_open--^^ ==================================================*)
1321 section \<open>Adapt SPARK's parser -> parse Formalise.T\<close>
1323 Possible models, where a file is read and parsed:
1324 * for *.bib see usage of Resources.provide_parse_files .. parsed by LaTeX
1325 * Outer_Syntax.command \ <command_keyword>\<open>external_file\<close> .. ?!?
1326 * Outer_Syntax.command \<command_keyword>\<open>spark_open\<close>
1327 We pursue the latter.
1328 From c.f.2b9b4b38ab96 we have found Fdl_Lexer.scan as the very model
1329 for scanning/parsing Formalise.T.
1332 subsection \<open>testbed separates Fdl_Lexer.scan + Fdl_Parser from SPARK code\<close>
1333 declare [[ML_print_depth = 7]] (* 3 7 10 20 999999999 *)
1336 (** )open Fdl_Parser( *conflict with some of Fdl_Lexer.* *)
1338 step 1: go top down and keep respective results according to trace from
1339 spark_open \<open>greatest_common_divisor/g_c_d\<close> SPARK/../Greatest_Common_Divisor.thy.
1340 (in the example this is simple: just watch the bottom of Output
1341 The following verification conditions remain to be proved:
1344 ! remove @~{print} from calling functions (higher level)
1345 once you go down to the called functions (lower level)
1346 in order to reduce noise and to focus the code under actual consideration.
1347 step 2: at bottom gather the most elementary funs for transformation
1348 of g_c_d_siv_content to args of Fdl_Lexer.scan
1349 step 3: parse the tokens created by Fdl_Lexer.scan
1352 \<close> ML \<open> (** high start level: parsing to header + VCs **)
1353 val parsed = Fdl_Parser.parse_vcs Fdl_Lexer.siv_header Position.start g_c_d_siv_content;
1354 \<close> ML \<open> (* ^^^^^^^^^ <<<<<------------------------------------------------------*)
1355 val ((banner, (date, time), (date2, time2), (string, string2)), ((str, str2), vcss)) = parsed;
1357 if banner = ("Semantic Analysis of SPARK Text",
1358 "Examiner Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1359 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K.") andalso
1360 (date, time) = (("29", "NOV", "2010"), ("14", "30", "10", NONE)) andalso
1361 (date2, time2) = (("29", "NOV", "2010"), ("14", "30", "11", NONE)) andalso
1363 ("SPARK Simplifier Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1364 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K.") andalso
1365 (str, str2) = ("procedure", "Greatest_Common_Divisor.G_C_D")
1366 then () else error "Fdl_Parser.parse_vcs header CHANGED";
1367 if length vcss = 11 (* verification conditions (VCs) from g_c_d_siv_content *) then
1369 ("path(s) from start to run-time check associated with statement of line 8",
1370 [("procedure_g_c_d_1", ([], [("1", Fdl_Parser.Ident "true")]))]) ::
1371 ("path(s) from start to run-time check associated with statement of line 8",
1372 [("procedure_g_c_d_2", ([], [("1", Fdl_Parser.Ident "true")]))]) ::
1373 ("path(s) from start to assertion of line 10",
1374 [("procedure_g_c_d_3", ([], [("1", Fdl_Parser.Ident "true")]))]) ::
1375 ("path(s) from assertion of line 10 to assertion of line 10",
1376 [("procedure_g_c_d_4",
1377 (("1", Fdl_Parser.Funct (">=", [Fdl_Parser.Ident "c", Fdl_Parser.Number 0])) ::
1378 ("2", Fdl_Parser.Funct (">", [Fdl_Parser.Ident "d", Fdl_Parser.Number 0])) :: _,
1380 | _ => error "Fdl_Parser.parse_vcs vcss CHANGED 1"
1381 else error "Fdl_Parser.parse_vcs vcss CHANGED 2";
1384 \<close> ML \<open> (* lower level 1: tokenize string to header + VCs *)
1385 val level1_header_toks =
1386 (* tokenize to header + VCs is NON-standard ..
1387 vvvvvvvv--- parses vvvvvvvvvv + vvvvvvvvv, but leaves vcsss as Token list*)
1388 Fdl_Lexer.tokenize Fdl_Lexer.siv_header Fdl_Lexer.c_comment Position.start g_c_d_siv_content;
1389 \<close> ML \<open> (* ^^^^^^^^ <<<<<-------------------------------------------------------------------*)
1390 val ((banner, (date, time), (date2, time2), (string, string2)), toks ) = level1_header_toks;
1392 if banner = ("Semantic Analysis of SPARK Text",
1393 "Examiner Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1394 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K.") andalso
1395 (date, time) = (("29", "NOV", "2010"), ("14", "30", "10", NONE)) andalso
1396 (date2, time2) = (("29", "NOV", "2010"), ("14", "30", "11", NONE)) andalso
1398 ("SPARK Simplifier Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1399 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K.")
1400 then () else error "Fdl_Lexer.tokenize header CHANGED";
1401 if length toks = 319 (* tokens for str :: str :: verification conditions from g_c_d_siv_content *) then
1403 Token (Keyword, "procedure", _(*Position.T*)) ::
1404 Token (Long_Ident, "Greatest_Common_Divisor.G_C_D", _(*Position.T*)) :: _ => ()
1405 | _ => error "Fdl_Lexer.tokenize tokens CHANGED 1"
1406 else error "Fdl_Lexer.tokenize header CHANGED 2";
1409 \<close> ML \<open> (* lower level 2: tokenize the string *)
1410 val chars = Fdl_Lexer.explode_pos g_c_d_siv_content(*_content*) Position.start;
1411 if length chars = 2886 then () else error "Fdl_Lexer.explode_pos g_c_d_siv_content CHANGED";
1412 val level2_header_toks = (Scan.finite char_stopper (*..from tokenize..*)
1413 (Scan.error (Fdl_Lexer.scan Fdl_Lexer.siv_header Fdl_Lexer.c_comment)) chars);
1414 (* ---------------------------------------------------------------------------\
1415 Fdl_Lexer.scan Fdl_Lexer.siv_header Fdl_Lexer.c_comment chars
1416 exception MORE () raised (line 176 of "General/scan.ML") ---------------------/ *)
1418 case level2_header_toks of
1419 (((("Semantic Analysis of SPARK Text",
1420 "Examiner Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1421 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K."),
1422 (("29", "NOV", "2010"), ("14", "30", "10", NONE)),
1423 (("29", "NOV", "2010"), ("14", "30", "11", NONE)),
1424 ("SPARK Simplifier Pro Edition, Version 9.1.0, Build Date 20101119, Build 19039",
1425 "Copyright (C) 2010 Altran Praxis Limited, Bath, U.K.")),
1426 Token (Keyword, "procedure", _) :: Token (Long_Ident, "Greatest_Common_Divisor.G_C_D", _) ::
1427 Token (Traceability,
1428 "path(s) from start to run-time check associated with statement of line 8", _) ::
1431 | _ => error "Fdl_Lexer.scan level2 CHANGED";
1434 \<close> ML \<open> (* lower level 2: parse the tokens *)
1435 val ((_, tokens), _) = level2_header_toks;
1437 Fdl_Parser.vcs: T list ->
1438 ((string * string) * (string * (string * ((string * Fdl_Parser.expr) list * (string * Fdl_Parser.expr) list)) list) list)
1440 (filter Fdl_Lexer.is_proper): T list -> T list;
1443 Scan.finite Fdl_Lexer.stopper (Scan.error (Fdl_Parser.!!! Fdl_Parser.vcs))
1444 (filter Fdl_Lexer.is_proper (*|*)tokens(*|*))
1445 (* ---------------------------------------------------------------------------\
1446 Fdl_Parser.vcs (*|*)tokens(*|*)
1447 exception ABORT fn raised (line 109 of "General/scan.ML") --------------------/ *)
1449 if parsed' = ((str, str2), vcss) then () else error "Fdl_Parser.parse_vcs level 2 CHANGED 2";
1453 subsection \<open>test data for Isac's Formalise.T parser\<close>
1456 val form_single_str = (
1458 (* Formalise.model: *)
1459 " [\"Traegerlaenge L\", \"Streckenlast q_0\", \"Biegelinie y\",\n" ^
1460 " \"Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]\",\n" ^
1461 " \"FunktionsVariable x\", \"GleichungsVariablen [c, c_2, c_3, c_4]\",\n" ^
1462 " \"AbleitungBiegelinie dy\"],\n" ^
1463 (* Formalise.spec: *)
1464 " (\"Biegelinie\", [\"Biegelinien\"], [\"IntegrierenUndKonstanteBestimmen2\"])\n" ^
1467 val formalise_str = "[" ^ form_single_str ^ "]"; (*..we assume one element ONLY *)
1470 (* Formalise.spec: *)
1471 " (\"Biegelinie\", [\"Biegelinien\"], [\"IntegrierenUndKonstanteBestimmen2\"])";
1472 val form_spec_str' =
1473 "(\"Biegelinie\",[\"Biegelinien\"],[\"IntegrierenUndKonstanteBestimmen2\"])";
1475 val form_model_str = (
1476 (* Formalise.model: *)
1477 " [\"Traegerlaenge L\", \"Streckenlast q_0\", \"Biegelinie y\",\n" ^
1478 " \"Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]\",\n" ^
1479 " \"FunktionsVariable x\", \"GleichungsVariablen [c, c_2, c_3, c_4]\",\n" ^
1480 " \"AbleitungBiegelinie dy\"],\n")
1481 val form_model_str' = ( (* NO whitespace *)
1482 "[\"Traegerlaenge L\",\"Streckenlast q_0\",\"Biegelinie y\",\"Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]\",\"FunktionsVariable x\", \"GleichungsVariablen [c, c_2, c_3, c_4]\",\"AbleitungBiegelinie dy\"]")
1484 val form_model_str'' = ( (* NO whitespace, NO [ ] *)
1485 "\"Traegerlaenge L\",\"Streckenlast q_0\",\"Biegelinie y\",\"Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]\",\"FunktionsVariable x\", \"GleichungsVariablen [c, c_2, c_3, c_4]\",\"AbleitungBiegelinie dy\"]")
1487 val form_model_str''' = ( (* NO whitespace, NO [ ], NO "," *)
1488 "[\"Traegerlaenge L\"\"Streckenlast q_0\"\"Biegelinie y\"\"Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]\"\"FunktionsVariable x\"\"GleichungsVariablen [c, c_2, c_3, c_4]\"\"AbleitungBiegelinie dy\"]")
1492 subsection \<open>Adapt SPARK's code for parsing Formalise.T\<close>
1494 \<close> ML \<open> (* equip the string -----vvvvvvvvvvvvvvv with Positions..*)
1495 val chars = Fdl_Lexer.explode_pos form_single_str Position.start: Fdl_Lexer.chars;
1496 if length chars = 306 then () else error "Fdl_Lexer.explode_pos g_c_d_siv CHANGED";
1499 subsubsection \<open>identify various code that might serve as model\<close>
1501 \<close> ML \<open> (* gen_comment adapted for a single string (*1*) on simplified form_model_str'' *)
1502 val tokenize_string = $$$ "\"" |-- !!! "unclosed string" (*2*)
1503 (Scan.repeat (Scan.unless ($$$ "\"") any) --| $$$ "\"") >> make_token Comment(*!!!*);
1504 tokenize_string: chars -> T * chars
1506 val chars = Fdl_Lexer.explode_pos form_model_str'' Position.start: Fdl_Lexer.chars;
1507 tokenize_string chars; (*3*) (* = WE ONLY GET THE FIRST ELEMENT tokenized, WHY?..
1508 (Token (Comment, "Traegerlaenge L", {line=1, offset=2}),
1509 [(",", {line=1, offset=18}), ("\"", {line=1, offset=19}), ("S", {line=1, offset=20}), ("t", {line=1, offset=21}), ("r", {line=1, offset=22}), ("e", {line=1, offset=23}), ("c", {line=1, offset=24}),
1510 ("k", {line=1, offset=25}), ("...", {line=1, offset=26}), ...])*)
1512 \<close> ML \<open> (* gen_comment adapted for several strings (*4*) on simplified form_model_str''' *)
1513 val tokenize_strings =
1514 Fdl_Lexer.keyword "[" |-- !!! "unclosed list"
1515 (Scan.repeat (Scan.unless (Fdl_Lexer.keyword "]") tokenize_string) --|
1516 Fdl_Lexer.keyword "]");
1517 tokenize_strings: chars -> T(*Token of kind * string * Position.T*) list * chars
1519 val chars = Fdl_Lexer.explode_pos form_model_str''' Position.start;
1520 tokenize_strings chars;(* = THIS LOOKS PROMISING..
1521 ([Token (Comment, "Traegerlaenge L", {line=1, offset=3}), Token (Comment, "Streckenlast q_0", {line=1, offset=20}), Token (Comment, "Biegelinie y", {line=1, offset=38}),
1522 Token (Comment, "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", {line=1, offset=52}), Token (Comment, "FunktionsVariable x", {line=1, offset=118}),
1523 Token (Comment, "GleichungsVariablen [c, c_2, c_3, c_4]", {line=1, offset=139}), Token (Comment, "AbleitungBiegelinie dy", {line=1, offset=179})],
1526 \<close> ML \<open> (*.. BUT THAT DOESN'T WORK FOR MORE REALISTIC DATA..*)
1527 val chars = Fdl_Lexer.explode_pos form_model_str' Position.start;
1529 tokenize_strings chars;
1530 exception ABORT fn raised (line 109 of "General/scan.ML")*)
1533 \<close> ML \<open> (*A NEW IDEA: postpone list-structure to Fld_Parser, now just make reasonable tokens *)
1534 val chars = Fdl_Lexer.explode_pos "\"GleichungsVariablen [c, c_2, c_3, c_4]\"" Position.start;
1535 tokenize_string chars; (* = (Token (Comment, "GleichungsVariablen [c, c_2, c_3, c_4]"*)
1537 \<close> ML \<open> (*..what about delimiters of lists?..*)
1538 \<close> ML \<open> (*let's go bottom up..*)
1543 xxx: chars -> ((chars * chars) * chars) * chars;
1548 keyword "[" -- tokenize_string;
1549 xxx: chars -> (((chars * chars) * chars) * T) * chars
1550 \<close> ML \<open> (* ^^^ list ?!*)
1554 keyword "(" -- whitespace --
1555 keyword "[" -- whitespace --
1557 xxx: chars -> (((((chars * chars) * chars) * chars) * chars) * T) * chars;
1558 \<close> ML \<open> (* how can we drop ^^^^^ ^^^^^ ^^ and make here ^^^ a list ?!
1559 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*)
1560 val chars = Fdl_Lexer.explode_pos "(\n [\"Traegerlaenge L\"" Position.start;
1562 xxx chars; (* = WE GET AN UNPLEASANT MIXTURE OF Fld_Lexer.T AND Fld_Lexer.char ..
1563 (((((([], [("(", {line=1, offset=1})]), [("\n", {line=1, offset=2}), (" ", {line=2, offset=3}), (" ", {line=2, offset=4})]), [("[", {line=2, offset=5})]), []),
1564 Token (Comment, "Traegerlaenge L", {line=2, offset=7})),
1567 tokenize_string: chars -> T * chars;
1568 whitespace: chars -> chars * chars;
1569 tokenize: (chars -> 'a * chars) -> (chars -> T * chars) -> Position.T -> string -> 'a * T list;
1570 Scan.repeat: ('a -> 'b * 'a) -> 'a -> 'b list * 'a
1571 (* ^^ ^^^^^^^ ^^^^^^*)
1575 subsubsection \<open>have a closer look at SPARKs main tokenizer\<close>
1577 \<close> ML \<open> Fdl_Lexer.scan; (*7*) (*.. <ctrl><mouse> leads to the source *)
1579 val aaa = (*remove code specific for SPARK..*)
1580 Scan.repeat (Scan.unless (Scan.one is_char_eof)
1582 (keyword "For" -- whitespace1) |--
1583 Scan.repeat1 (Scan.unless (keyword ":") any) --|
1584 keyword ":" >> make_token Traceability
1585 || Scan.max leq_token
1586 (Scan.literal lexicon >> make_token Keyword)
1587 ( long_identifier >> make_token Long_Ident
1588 || identifier >> make_token Ident
1590 || number >> make_token Number
1593 \<close> ML \<open> (* we investigate the alternatives || and confirm observations from tracing:
1594 EACH ROUND OF LEXING CREATES one TOKEN ----------------------vvv *)
1595 (*fun scan header comment = ... (*8*)
1597 (*||*)(keyword "For" -- whitespace1) |--
1598 Scan.repeat1 (Scan.unless (keyword ":") any) --|
1599 keyword ":" >> make_token Traceability : chars -> T * chars;
1600 (*||*)Scan.max leq_token
1601 (Scan.literal lexicon >> make_token Keyword)
1602 ( long_identifier >> make_token Long_Ident
1603 || identifier >> make_token Ident
1604 ) : chars -> T * chars;
1605 (*||*)number >> make_token Number : chars -> T * chars;
1606 (* ----------------------^^^ *)
1609 Scan.repeat (Scan.unless (Scan.one is_char_eof) (*8b*)
1610 ((**) (tokenize_string (**)-- whitespace(**)) (* reads a first string including , ] *)
1611 (**)|| (keyword "," >> tokenize_string) (* further element of string list ?" " *)
1612 (**)|| ((Scan.max leq_token (* *)
1613 (**) (Scan.literal lexicon >> make_token Keyword)(**)
1614 (**) ( long_identifier >> make_token Long_Ident(**)
1615 (**) || identifier >> make_token Ident) (**)
1616 (**) ) -- whitespace) (**)
1620 val chars = Fdl_Lexer.explode_pos "\"aa\",\"bb\"] ##" Position.start;
1622 aaa chars; (* --------vvvv here we get both as Tokens, list elements AND list delimiters
1623 ([(Token (Comment, "aa", {line=1, offset=2}), []), (*6a*)
1624 (Token (Keyword, ",", {line=1, offset=5}), []),
1625 (Token (Comment, "bb", {line=1, offset=7}), []),
1626 (Token (Keyword, "]", {line=1, offset=10}),
1627 [(" ", {line=1, offset=11})])],
1628 [("#", {line=1, offset=12}), ("#", {line=1, offset=13})])*)
1631 \<close> ML \<open> (* what is this part of scan doing ..*) (*8*)
1632 val yyy = Scan.max leq_token
1633 (Scan.literal lexicon >> make_token Keyword)
1634 ( long_identifier >> make_token Long_Ident
1635 || identifier >> make_token Ident);
1636 yyy: chars -> T * chars;
1638 val chars = Fdl_Lexer.explode_pos "For " Position.start;
1639 (**)yyy chars;(* = (Token (Keyword, "For", {line=1, offset=1}), [(" ", ..*)
1641 val chars = Fdl_Lexer.explode_pos ", " Position.start;
1642 (**)yyy chars;(* = (Token (Keyword, ",", {line=1, offset=1}), [(" ", ..*)
1644 val chars = Fdl_Lexer.explode_pos " , " Position.start;
1645 (** )yyy chars;( * exception FAIL NONE raised (line 204 of "General/scan.ML") *)
1647 val chars = Fdl_Lexer.explode_pos "id " Position.start;
1648 (**)yyy chars;(* = (Token (Ident, "id", {line=1, offset=1}), [(" ", ..*)
1650 val chars = Fdl_Lexer.explode_pos "spec.id " Position.start;
1651 (**)yyy chars;(* = (Token (Long_Ident, "spec.id", {line=1, offset=1}), [(" ", ..*)
1652 \<close> ML \<open> (*..we see: this part of scan handles whitespace perfectly! *)
1656 subsubsection \<open>play with function types and construct them systematically\<close>
1658 \<close> ML \<open> (* string list is a string || keyword "," || whitespace*) (*10*)
1659 tokenize_string : chars -> T * chars;
1660 keyword "," >> make_token Keyword: chars -> T * chars;
1661 whitespace : chars -> chars * chars; (*? ? ? how make this of equal type *)
1663 val chars = Fdl_Lexer.explode_pos ", " Position.start; (*11*)
1665 (* = ([], [(",", {line=1, offset=1}), (" ", {line=1, offset=2}), (" ", {line=1, offset=3})])*)
1667 val chars = Fdl_Lexer.explode_pos " ," Position.start; (*11*)
1669 (* = ([(" ", {line=1, offset=1}), (" ", {line=1, offset=2})], [(",", {line=1, offset=3})])*)
1671 val chars = Fdl_Lexer.explode_pos " , " Position.start; (*11*)
1673 (* = ([(" ", {line=1, offset=1})], [(",", {line=1, offset=2}), (" ", {line=1, offset=3})])*)
1676 \<close> ML \<open> (* investigate (whitespace -- keyword "," -- whitespace) >> make_token Keyword*)
1678 val xxx = (* this nicely separates whitespace from "," *) (*12*)
1679 (whitespace -- keyword "," -- whitespace): chars -> ((chars * chars) * chars) * chars;
1680 val chars = Fdl_Lexer.explode_pos " , ." Position.start;
1683 [(" ", {line=1, offset=1}), (" ", {line=1, offset=2}), (" ", {line=1, offset=3})],
1684 \<longrightarrow> [(",", {line=1, offset=4})]),
1685 [(" ", {line=1, offset=5}), (" ", {line=1, offset=6}), (" ", {line=1, offset=7})]),
1686 [(".", {line=1, offset=8})])
1687 ^^^^^^^^^^^^^^^^^^^^^^ this nicely separates whitespace from "," ^^^^^^^^^^^^^^^^^^^^^*)
1689 tokenize_string : chars -> T * chars;
1690 (*whitespace*)keyword ","(*whitespace*) >> make_token Keyword : chars -> T * chars;
1691 (* we want this type uniformly for || ^^^^^^^^^^^^^^^^^^^^^ *)
1693 val eee = (fn (((_, chs1), _), chs2) => (chs1, chs2)) : (('a * 'b) * 'c) * 'd -> 'b * 'd; (*14*)
1694 \<close> text \<open> HOW CORRECT THIS...
1695 (whitespace -- keyword "," -- whitespace) >> (fn (((_, chs1), _), chs2) => (chs1, chs2));
1696 ERROR Can't unify (string * Position.T) list to 'a * 'b
1698 val fff = (fn (((_, chars), _), _) => chars) : (('a * 'b) * 'c) * 'd -> 'b;(*14*)
1699 val ggg = (fn _ => (fn (((_, chars), _), _) => chars)) : 'a -> (('b * 'c) * 'd) * 'e -> 'c;
1700 val hhh = (fn xxx => (fn (((_, chars), _), _) => chars) xxx): (('a * 'b) * 'c) * 'd -> 'b;
1701 val iii = (fn ((_, chars), _) => make_token Keyword chars)
1702 : ('a * chars) * 'b -> T
1704 \<close> ML \<open> (*after above trials we use this pattern for building comma_spaced *) (*11a*)
1705 keyword "," : chars -> chars * chars;
1706 make_token Keyword : chars -> T ;
1707 keyword "," >> make_token Keyword : chars -> T * chars;
1709 tokenize_string : chars -> T * chars;
1710 whitespace : chars -> chars * chars;
1713 val space_comma_space = xxx;
1714 val make_token_comma = iii;
1715 val comma_spaced = space_comma_space >> make_token_comma
1717 xxx : chars -> ((chars * chars) * chars) * chars;
1719 space_comma_space : chars -> ((chars * chars) * chars) * chars;
1720 make_token_comma : ((chars * chars) * chars) -> T ;
1721 comma_spaced : chars -> T * chars; (**)
1723 val chars = Fdl_Lexer.explode_pos " , ." Position.start;
1724 comma_spaced chars; (*(Token (Keyword, ",", {line=1, offset=4}), [(".", {line=1, offset=8})])*)
1725 (*\--------- found right type for arguments of Scan.repeat ---------------------------------/*)
1728 \<close> ML \<open> (*we use that for a list tokenizer..*) (*13*)
1730 Scan.repeat (tokenize_string || comma_spaced);
1731 string_list: chars -> T list * chars
1733 val chars = Fdl_Lexer.explode_pos form_model_str'' Position.start;
1734 \<close> ML \<open> (* tokenize_string_list works..*)
1735 string_list chars; (* =
1736 ([Token (Comment, "Traegerlaenge L", {line=1, offset=2}) , Token (Keyword, ",", {line=1, offset=18}),
1737 Token (Comment, "Streckenlast q_0", {line=1, offset=20}), Token (Keyword, ",", {line=1, offset=37}),
1738 Token (Comment, "Biegelinie y", {line=1, offset=39}) , Token (Keyword, ",", {line=1, offset=52}),
1739 Token (Comment, "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", {line=1, offset=54}),
1740 Token (Keyword, ",", {line=1, offset=119}),
1741 Token (Comment, "FunktionsVariable x", {line=1, offset=121}),
1742 Token (Keyword, ",", {line=1, offset=141}),
1743 Token (Comment, "GleichungsVariablen [c, c_2, c_3, c_4]", {line=1, offset=144}),
1744 Token (Keyword, ",", {line=1, offset=183}),
1745 Token (Comment, "AbleitungBiegelinie dy", {line=1, offset=185})],
1746 [("]", {line=1, offset=208})])*)
1749 \<close> ML \<open> (*but how connect with tokenizing other parts?..*)
1750 string_list : chars -> T list * chars;
1751 Scan.repeat1: ('a -> 'b * 'a ) -> 'a -> 'b list * 'a;
1752 Scan.repeat1: (chars -> 'b * chars) -> chars -> 'b list * chars;
1754 op @@@ : ('a -> 'b list * 'c) * ('c -> 'b list * 'd) -> 'a -> 'b list * 'd;
1755 op ::: : ('a -> 'b * 'c) * ('c -> 'b list * 'd) -> 'a -> 'b list * 'd;
1756 op -- : ('a -> 'b * 'c) * ('c -> 'd * 'e) -> 'a -> ('b * 'd) * 'e
1760 subsubsection \<open>adapt Fdl_Lexer.scan to a tokenizer\<close>
1762 \<close> ML \<open> Fdl_Lexer.scan; (*<ctrl><mouse-click> jumps to the code*) (*14*)
1763 \<close> ML \<open> (*the first top down trial fails..*)
1765 (*fun scan (*header comment*) =
1766 ( *!!! "bad header" header --| whitespace --*)
1767 Scan.repeat (Scan.unless (Scan.one is_char_eof)
1770 ||*)(keyword "For" -- whitespace1) |--
1771 Scan.repeat1 (Scan.unless (keyword ":") any) --|
1772 keyword ":" >> make_token Traceability
1773 || Scan.max leq_token
1774 (Scan.literal lexicon >> make_token Keyword)
1775 ( long_identifier >> make_token Long_Ident
1776 || identifier >> make_token Ident)
1777 (*|| number >> make_token Number*)) --|
1779 xxx: chars -> T list * chars;
1780 \<close> ML \<open> (*.. but we see, that the scanner delivers a token per call..*)
1782 \<close> ML \<open> (*we want a string like "GleichungsVariablen [c, c_2, c_3, c_4]" in ONE token*)
1783 val chars = Fdl_Lexer.explode_pos (form_single_str ^ ",") Position.start;
1786 ( ** )ERROR exception ABORT fn raised (line 109 of "General/scan.ML")( **)
1789 \<close> ML \<open> (*we have to tokenize [ and ] and , explicitly..*)
1791 keyword "[" -- whitespace --
1792 Scan.repeat (tokenize_string || comma_spaced) --
1795 val chars = Fdl_Lexer.explode_pos (form_model_str' ^ ".") Position.start;
1796 xxx chars; (* = AGAIN WE GET AN UNPLEASANT MIXTURE..
1797 (((([("[", {line=1, offset=1})], []),
1798 [Token (Comment, "Traegerlaenge L", {line=1, offset=3}), Token (Keyword, ",", {line=1, offset=19}), Token (Comment, "Streckenlast q_0", {line=1, offset=21}), Token (Keyword, ",", {line=1, offset=38}),
1799 Token (Comment, "Biegelinie y", {line=1, offset=40}), Token (Keyword, ",", {line=1, offset=53}), Token (Comment, "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", {line=1, offset=55}),
1800 Token (Keyword, ",", {line=1, offset=120}), Token (Comment, "FunktionsVariable x", {line=1, offset=122}), Token (Keyword, ",", {line=1, offset=142}),
1801 Token (Comment, "GleichungsVariablen [c, c_2, c_3, c_4]", {line=1, offset=145}), Token (Keyword, ",", {line=1, offset=184}), Token (Comment, "AbleitungBiegelinie dy", {line=1, offset=186})]),
1802 [("]", {line=1, offset=209})]),
1803 [(".", {line=1, offset=210})])*)
1806 \<close> ML \<open> (* IDEA COMBINING (*8*) and (*13*) for (*15*):
1807 we do NOT tokenize the whole (string) list, but tokenize_string FIRST *)
1809 (*fun scan (*header comment*) =
1810 ( *!!! "bad header" header --| whitespace --*)
1811 Scan.repeat (Scan.unless (Scan.one is_char_eof)
1813 ( tokenize_string (*.. THIS MUST BE FIRST *)
1815 ||(keyword "For" -- whitespace1) |--
1816 Scan.repeat1 (Scan.unless (keyword ":") any) --|
1817 keyword ":" >> make_token Traceability*)
1818 ||Scan.max leq_token
1819 (Scan.literal lexicon >> make_token Keyword)
1820 ( long_identifier >> make_token Long_Ident
1821 || identifier >> make_token Ident)
1822 (*|| number >> make_token Number*) ) --|
1824 scan: chars -> T list * chars;
1826 val chars = Fdl_Lexer.explode_pos (form_single_str ^ ",") Position.start;
1829 ( ** )ERROR exception ABORT fn raised (line 109 of "General/scan.ML")( **)
1830 \<close> ML \<open> (*BUT WITH THE WRAPPER IN tokenize THAT WORKS..*)
1831 (*fun tokenize_formalise pos str = KEEP IDENTIFIERS CLOSE TO SPARK..*)
1833 (Scan.finite char_stopper
1834 (Scan.error scan) (explode_pos str pos));
1836 val (toks, _) = scan' Position.start formalise_str
1838 (*it = ----------------------------------------------------------------- IS PEFECT ! ! ! !
1839 ([Token (Keyword, "[", {line=1, offset=1}),
1840 Token (Keyword, "(", {line=1, offset=2}),
1841 Token (Keyword, "[", {line=2, offset=6}),
1842 Token (Comment, "Traegerlaenge L", {line=2, offset=8}), Token (Keyword, ",", {line=2, offset=24}), Token (Comment, "Streckenlast q_0", {line=2, offset=27}), Token (Keyword, ",", {line=2, offset=44}), Token (Comment, "Biegelinie y", {line=2, offset=47}), Token (Keyword, ",", {line=2, offset=60}), Token (Comment, "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", {line=3, offset=67}), Token (Keyword, ",", {line=3, offset=132}), Token (Comment, "FunktionsVariable x", {line=4, offset=139}), Token (Keyword, ",", {line=4, offset=159}), Token (Comment, "GleichungsVariablen [c, c_2, c_3, c_4]", {line=4, offset=162}), Token (Keyword, ",", {line=4, offset=201}), Token (Comment, "AbleitungBiegelinie dy", {line=5, offset=208}),
1843 Token (Keyword, "]", {line=5, offset=231}),
1844 Token (Keyword, ",", {line=5, offset=232}),
1845 Token (Keyword, "(", {line=6, offset=236}),
1846 Token (Comment, "Biegelinie", {line=6, offset=238}),
1847 Token (Keyword, ",", {line=6, offset=249}),
1848 Token (Keyword, "[", {line=6, offset=251}),
1849 Token (Comment, "Biegelinien", {line=6, offset=253}),
1850 Token (Keyword, "]", {line=6, offset=265}),
1851 Token (Keyword, ",", {line=6, offset=266}),
1852 Token (Keyword, "[", {line=6, offset=268}),
1853 Token (Comment, "IntegrierenUndKonstanteBestimmen2", {line=6, offset=270}),
1854 Token (Keyword, "]", {line=6, offset=304}),
1855 Token (Keyword, ")", {line=6, offset=305}),
1856 Token (Keyword, ")", {line=7, offset=307}),
1857 Token (Keyword, "]", {line=7, offset=308})],
1859 \-- ^^ chars EXHAUSTED, PEFECT *)
1864 subsubsection \<open>Implement the parser\<close>
1866 \<close> ML \<open> (*the only difference between Parse and Fdl_Parser is Token.T versus Fdl_Lexer.T *)
1868 string -> 'a parser -> 'a list parser;
1870 string -> (Token.T list -> 'a * Token.T list) -> Token.T list -> 'a list * Token.T list;
1872 string -> (Fdl_Lexer.T list -> 'a * Fdl_Lexer.T list) -> Fdl_Lexer.T list -> 'a list * Fdl_Lexer.T list;
1874 \<close> ML \<open> (*we start with the initial parentheses..*)
1876 Fdl_Parser.$$$ "[" --
1877 Fdl_Parser.$$$ "(" --
1878 Fdl_Parser.$$$ "[" |--
1879 Fdl_Parser.!!! (Fdl_Parser.list1 Fdl_Parser.identifier --|
1881 \<close> ML \<open> (*need string_list_parser instead ^^^^^^^^^^^^^^^^^^^^^*)
1882 \<close> ML \<open> (*..vvvvvvvvvv is our model..*)
1883 Fdl_Parser.identifier: T list -> string * T list;
1884 \<close> ML \<open> (*we have..*)
1885 tokenize_string : chars -> T * chars; (*we need:
1886 parse_string : T list -> string * T list; *)
1888 \<close> ML \<open> (*in analogy to Fdl_Parser ..*)
1889 val identifier = Fdl_Parser.group "identifier"
1890 (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Ident) >>
1891 Fdl_Lexer.content_of);
1892 \<close> ML \<open> (*.. we implement..*)
1893 val parse_string = Fdl_Parser.group "string"
1894 (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Comment) >>
1895 Fdl_Lexer.content_of);
1896 parse_string : T list -> string * T list;
1897 \<close> ML \<open> (*we copy the structure from *101* *)
1899 Fdl_Parser.$$$ "[" --
1900 Fdl_Parser.$$$ "(" --
1901 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1902 Fdl_Parser.list1 parse_string --|
1903 Fdl_Parser.$$$ "]")) --
1904 Fdl_Parser.$$$ "," --
1905 Fdl_Parser.$$$ "(" --
1906 parse_string -- (* "Biegelinie" *)
1907 Fdl_Parser.$$$ "," --
1908 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1909 Fdl_Parser.list1 parse_string --| (* ["Biegelinien"] *)
1910 Fdl_Parser.$$$ "]")) --
1911 Fdl_Parser.$$$ "," --
1912 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1913 Fdl_Parser.list1 parse_string --| (* ["IntegrierenUndKonstanteBestimmen2"] *)
1914 Fdl_Parser.$$$ "]")) --
1915 Fdl_Parser.$$$ ")" --
1916 Fdl_Parser.$$$ ")" --
1918 \<close> ML \<open> (*.. this compiles correctly, but we modularise into parse_form_model..*)
1919 val parse_form_model =
1920 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1921 Fdl_Parser.list1 parse_string --|
1922 Fdl_Parser.$$$ "]"));
1923 parse_form_model: T list -> string list * T list;
1925 type form_model = string list;
1926 parse_form_model: T list -> form_model * T list
1928 \<close> ML \<open> (*.. and into parse_form_refs..*)
1929 val parse_form_refs =
1930 Fdl_Parser.$$$ "(" --
1931 parse_string -- (* "Biegelinie" *)
1932 Fdl_Parser.$$$ "," --
1933 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1934 Fdl_Parser.list1 parse_string --| (* ["Biegelinien"] *)
1935 Fdl_Parser.$$$ "]")) --
1936 Fdl_Parser.$$$ "," --
1937 (Fdl_Parser.$$$ "[" |-- Fdl_Parser.!!! (
1938 Fdl_Parser.list1 parse_string --| (* ["IntegrierenUndKonstanteBestimmen2"] *)
1939 Fdl_Parser.$$$ "]")) --
1941 parse_form_refs: T list -> ((((((string * string) * string) * string list) * string) * string list) * string) * T list;
1943 type form_refs = (((((string * string) * string) * string list) * string) * string list) * string;
1944 parse_form_refs: T list -> form_refs * T list; (*..how can we use this type --------------vvvvv*)
1946 \<close> ML \<open> (*we combinge parse_form_model and parse_form_refs..*)
1947 (*val parse_formalise = KEEP IDENTIFIERS CLOSE TO SPARK..*)
1950 Fdl_Parser.$$$ "[" --
1951 Fdl_Parser.$$$ "(" --
1953 Fdl_Parser.$$$ "," --
1955 Fdl_Parser.$$$ ")" --
1956 Fdl_Parser.$$$ "]");
1958 vcs: T list -> ((((((string * string) * form_model) * string) * (*------------refs..*)
1959 ((((((string * string) * string) * string list) * string) * string list) * string)) * string) * string) * T list;
1961 \<close> ML \<open> (*we use code from the parser..*)
1962 val (parsed', []) = (*TODO *##* *)
1963 Scan.finite Fdl_Lexer.stopper (Scan.error (Fdl_Parser.!!! vcs)) toks;
1964 (*see SPARK 99, but ..^^^^^^^ we don't need that ---------vvv vvvv*)
1966 val (parsed', []) = vcs toks;
1967 \<close> ML \<open> (*..however, we adopt vvvvvvvvvvvvvvvvvvvvvvvvvv error handling*)
1968 val (parsed', []) = (Scan.error (Fdl_Parser.!!! vcs)) toks;
1974 [ "Traegerlaenge L", "Streckenlast q_0", "Biegelinie y",
1975 "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", "FunktionsVariable x",
1976 "GleichungsVariablen [c, c_2, c_3, c_4]", "AbleitungBiegelinie dy"
1984 ["IntegrierenUndKonstanteBestimmen2"]),
1988 | _ => error "parse_formalise CHANGED";
1990 \<close> ML \<open> (*we read out Formalisation.T from the parser's result..*)
1991 fun read_out_formalise ((((( (
1994 form_model: TermC.as_string list),
1999 probl_id: Problem.id),
2001 meth_id: Method.id),
2004 "]") = [(form_model, (thy_id, probl_id, meth_id))]
2005 | read_out_formalise _ =
2006 raise ERROR "read_out_formalise: WRONGLY parsed";
2008 (((((string * string) * TermC.as_string list) * string) *
2009 ((((((string * ThyC.id) * string) * Problem.id) * string) * Method.id) * string)) * string) * string ->
2010 (TermC.as_string list * (ThyC.id * Problem.id * Method.id)) list;
2012 type formalise = (((((string * string) * TermC.as_string list) * string) *
2013 ((((((string * ThyC.id) * string) * Problem.id) * string) * Method.id) * string)) * string) * string;
2014 read_out_formalise: formalise -> Formalise.T list
2016 if (read_out_formalise parsed' : Formalise.T list ) =
2017 [(["Traegerlaenge L", "Streckenlast q_0", "Biegelinie y",
2018 "Randbedingungen [y 0 = (0::real), y L = 0, M_b 0 = 0, M_b L = 0]", "FunktionsVariable x",
2019 "GleichungsVariablen [c, c_2, c_3, c_4]", "AbleitungBiegelinie dy"],
2020 ("Biegelinie", ["Biegelinien"], ["IntegrierenUndKonstanteBestimmen2"]))]
2021 then () else error "read_out_formalise CHANGED";