40 |
40 |
41 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
41 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
42 val simp_attrs = @{attributes [simp]}; |
42 val simp_attrs = @{attributes [simp]}; |
43 val code_nitpicksimp_attrs = Code.add_default_eqn_attrib :: nitpicksimp_attrs; |
43 val code_nitpicksimp_attrs = Code.add_default_eqn_attrib :: nitpicksimp_attrs; |
44 |
44 |
45 exception Primcorec_Error of string * term list; |
45 exception PRIMCOREC of string * term list; |
46 |
46 |
47 fun primcorec_error str = raise Primcorec_Error (str, []); |
47 fun primcorec_error str = raise PRIMCOREC (str, []); |
48 fun primcorec_error_eqn str eqn = raise Primcorec_Error (str, [eqn]); |
48 fun primcorec_error_eqn str eqn = raise PRIMCOREC (str, [eqn]); |
49 fun primcorec_error_eqns str eqns = raise Primcorec_Error (str, eqns); |
49 fun primcorec_error_eqns str eqns = raise PRIMCOREC (str, eqns); |
50 |
50 |
51 datatype primcorec_option = Sequential_Option | Exhaustive_Option; |
51 datatype primcorec_option = Sequential_Option | Exhaustive_Option; |
52 |
52 |
53 datatype corec_call = |
53 datatype corec_call = |
54 Dummy_No_Corec of int | |
54 Dummy_No_Corec of int | |
81 nested_maps: thm list, |
81 nested_maps: thm list, |
82 nested_map_idents: thm list, |
82 nested_map_idents: thm list, |
83 nested_map_comps: thm list, |
83 nested_map_comps: thm list, |
84 ctr_specs: corec_ctr_spec list}; |
84 ctr_specs: corec_ctr_spec list}; |
85 |
85 |
86 exception AINT_NO_MAP of term; |
86 exception NOT_A_MAP of term; |
87 |
87 |
88 fun not_codatatype ctxt T = |
88 fun not_codatatype ctxt T = |
89 error ("Not a codatatype: " ^ Syntax.string_of_typ ctxt T); |
89 error ("Not a codatatype: " ^ Syntax.string_of_typ ctxt T); |
90 fun ill_formed_corec_call ctxt t = |
90 fun ill_formed_corec_call ctxt t = |
91 error ("Ill-formed corecursive call: " ^ quote (Syntax.string_of_term ctxt t)); |
91 error ("Ill-formed corecursive call: " ^ quote (Syntax.string_of_term ctxt t)); |
257 val fs' = |
257 val fs' = |
258 map_flattened_map_args ctxt s (map3 (massage_map_or_map_arg bound_Ts) Us Ts) fs; |
258 map_flattened_map_args ctxt s (map3 (massage_map_or_map_arg bound_Ts) Us Ts) fs; |
259 in |
259 in |
260 Term.list_comb (map', fs') |
260 Term.list_comb (map', fs') |
261 end |
261 end |
262 | NONE => raise AINT_NO_MAP t) |
262 | NONE => raise NOT_A_MAP t) |
263 | massage_map _ _ _ t = raise AINT_NO_MAP t |
263 | massage_map _ _ _ t = raise NOT_A_MAP t |
264 and massage_map_or_map_arg bound_Ts U T t = |
264 and massage_map_or_map_arg bound_Ts U T t = |
265 if T = U then |
265 if T = U then |
266 tap check_no_call t |
266 tap check_no_call t |
267 else |
267 else |
268 massage_map bound_Ts U T t |
268 massage_map bound_Ts U T t |
269 handle AINT_NO_MAP _ => massage_mutual_fun bound_Ts U T t |
269 handle NOT_A_MAP _ => massage_mutual_fun bound_Ts U T t |
270 and massage_mutual_fun bound_Ts U T t = |
270 and massage_mutual_fun bound_Ts U T t = |
271 (case t of |
271 (case t of |
272 Const (@{const_name comp}, _) $ t1 $ t2 => |
272 Const (@{const_name comp}, _) $ t1 $ t2 => |
273 mk_comp bound_Ts (massage_mutual_fun bound_Ts U T t1, tap check_no_call t2) |
273 mk_comp bound_Ts (massage_mutual_fun bound_Ts U T t1, tap check_no_call t2) |
274 | _ => |
274 | _ => |
305 | t1 $ t2 => |
305 | t1 $ t2 => |
306 (if has_call t2 then |
306 (if has_call t2 then |
307 massage_mutual_call bound_Ts U T t |
307 massage_mutual_call bound_Ts U T t |
308 else |
308 else |
309 massage_map bound_Ts U T t1 $ t2 |
309 massage_map bound_Ts U T t1 $ t2 |
310 handle AINT_NO_MAP _ => massage_mutual_call bound_Ts U T t) |
310 handle NOT_A_MAP _ => massage_mutual_call bound_Ts U T t) |
311 | Abs (s, T', t') => |
311 | Abs (s, T', t') => |
312 Abs (s, T', massage_call (T' :: bound_Ts) (range_type U) (range_type T) t') |
312 Abs (s, T', massage_call (T' :: bound_Ts) (range_type U) (range_type T) t') |
313 | _ => massage_mutual_call bound_Ts U T t)) |
313 | _ => massage_mutual_call bound_Ts U T t)) |
314 | _ => ill_formed_corec_call ctxt t) |
314 | _ => ill_formed_corec_call ctxt t) |
315 else |
315 else |
592 fun dissect_coeqn_sel fun_names (basic_ctr_specss : basic_corec_ctr_spec list list) eqn_pos |
592 fun dissect_coeqn_sel fun_names (basic_ctr_specss : basic_corec_ctr_spec list list) eqn_pos |
593 ctr_rhs_opt code_rhs_opt eqn0 of_spec_opt eqn = |
593 ctr_rhs_opt code_rhs_opt eqn0 of_spec_opt eqn = |
594 let |
594 let |
595 val (lhs, rhs) = HOLogic.dest_eq eqn |
595 val (lhs, rhs) = HOLogic.dest_eq eqn |
596 handle TERM _ => |
596 handle TERM _ => |
597 primcorec_error_eqn "malformed function equation (expected \"lhs = rhs\")" eqn; |
597 primcorec_error_eqn "malformed function equation (expected \"lhs = rhs\")" eqn; |
598 val sel = head_of lhs; |
598 val sel = head_of lhs; |
599 val ((fun_name, fun_T), fun_args) = dest_comb lhs |> snd |> strip_comb |> apfst dest_Free |
599 val ((fun_name, fun_T), fun_args) = dest_comb lhs |> snd |> strip_comb |> apfst dest_Free |
600 handle TERM _ => |
600 handle TERM _ => |
601 primcorec_error_eqn "malformed selector argument in left-hand side" eqn; |
601 primcorec_error_eqn "malformed selector argument in left-hand side" eqn; |
602 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name) |
602 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name) |
603 handle Option.Option => |
603 handle Option.Option => |
604 primcorec_error_eqn "malformed selector argument in left-hand side" eqn; |
604 primcorec_error_eqn "malformed selector argument in left-hand side" eqn; |
605 val {ctr, ...} = |
605 val {ctr, ...} = |
606 (case of_spec_opt of |
606 (case of_spec_opt of |
607 SOME of_spec => the (find_first (curry (op =) of_spec o #ctr) basic_ctr_specs) |
607 SOME of_spec => the (find_first (curry (op =) of_spec o #ctr) basic_ctr_specs) |
608 | NONE => filter (exists (curry (op =) sel) o #sels) basic_ctr_specs |> the_single |
608 | NONE => filter (exists (curry (op =) sel) o #sels) basic_ctr_specs |> the_single |
609 handle List.Empty => primcorec_error_eqn "ambiguous selector - use \"of\"" eqn); |
609 handle List.Empty => primcorec_error_eqn "ambiguous selector - use \"of\"" eqn); |
1352 val ((fixes, specs), _) = Specification.read_spec raw_fixes raw_specs lthy; |
1352 val ((fixes, specs), _) = Specification.read_spec raw_fixes raw_specs lthy; |
1353 in |
1353 in |
1354 add_primcorec_ursive auto opts fixes specs of_specs_opt lthy |
1354 add_primcorec_ursive auto opts fixes specs of_specs_opt lthy |
1355 handle ERROR str => primcorec_error str |
1355 handle ERROR str => primcorec_error str |
1356 end |
1356 end |
1357 handle Primcorec_Error (str, eqns) => |
1357 handle PRIMCOREC (str, eqns) => |
1358 if null eqns |
1358 if null eqns then |
1359 then error ("primcorec error:\n " ^ str) |
1359 error ("primcorec error:\n " ^ str) |
1360 else error ("primcorec error:\n " ^ str ^ "\nin\n " ^ |
1360 else |
1361 space_implode "\n " (map (quote o Syntax.string_of_term lthy) eqns)); |
1361 error ("primcorec error:\n " ^ str ^ "\nin\n " ^ |
|
1362 space_implode "\n " (map (quote o Syntax.string_of_term lthy) eqns)); |
1362 |
1363 |
1363 val add_primcorecursive_cmd = (fn (goalss, after_qed, lthy) => |
1364 val add_primcorecursive_cmd = (fn (goalss, after_qed, lthy) => |
1364 lthy |
1365 lthy |
1365 |> Proof.theorem NONE after_qed goalss |
1366 |> Proof.theorem NONE after_qed goalss |
1366 |> Proof.refine (Method.primitive_text (K I)) |
1367 |> Proof.refine (Method.primitive_text (K I)) |