120 |
120 |
121 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
121 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
122 val simp_attrs = @{attributes [simp]}; |
122 val simp_attrs = @{attributes [simp]}; |
123 |
123 |
124 fun use_primcorecursive () = |
124 fun use_primcorecursive () = |
125 error ("\"auto\" failed (try " ^ quote (#1 @{command_keyword primcorecursive}) ^ " instead of " ^ |
125 error ("\"auto\" failed (try " ^ quote (#1 \<^command_keyword>\<open>primcorecursive\<close>) ^ " instead of " ^ |
126 quote (#1 @{command_keyword primcorec}) ^ ")"); |
126 quote (#1 \<^command_keyword>\<open>primcorec\<close>) ^ ")"); |
127 |
127 |
128 datatype corec_option = |
128 datatype corec_option = |
129 Plugins_Option of Proof.context -> Plugin_Name.filter | |
129 Plugins_Option of Proof.context -> Plugin_Name.filter | |
130 Sequential_Option | |
130 Sequential_Option | |
131 Exhaustive_Option | |
131 Exhaustive_Option | |
182 abs 0 |
182 abs 0 |
183 end; |
183 end; |
184 |
184 |
185 val abs_tuple_balanced = HOLogic.tupled_lambda o mk_tuple_balanced; |
185 val abs_tuple_balanced = HOLogic.tupled_lambda o mk_tuple_balanced; |
186 |
186 |
187 fun curried_type (Type (@{type_name fun}, [Type (@{type_name prod}, Ts), T])) = |
187 fun curried_type (Type (\<^type_name>\<open>fun\<close>, [Type (\<^type_name>\<open>prod\<close>, Ts), T])) = |
188 Ts ---> T; |
188 Ts ---> T; |
189 |
189 |
190 fun sort_list_duplicates xs = map snd (sort (int_ord o apply2 fst) xs); |
190 fun sort_list_duplicates xs = map snd (sort (int_ord o apply2 fst) xs); |
191 |
191 |
192 val mk_conjs = try (foldr1 HOLogic.mk_conj) #> the_default @{const True}; |
192 val mk_conjs = try (foldr1 HOLogic.mk_conj) #> the_default @{const True}; |
239 let |
239 let |
240 val thy = Proof_Context.theory_of ctxt; |
240 val thy = Proof_Context.theory_of ctxt; |
241 |
241 |
242 fun fld conds t = |
242 fun fld conds t = |
243 (case Term.strip_comb t of |
243 (case Term.strip_comb t of |
244 (Const (@{const_name Let}, _), [_, _]) => fld conds (unfold_lets_splits t) |
244 (Const (\<^const_name>\<open>Let\<close>, _), [_, _]) => fld conds (unfold_lets_splits t) |
245 | (Const (@{const_name If}, _), [cond, then_branch, else_branch]) => |
245 | (Const (\<^const_name>\<open>If\<close>, _), [cond, then_branch, else_branch]) => |
246 fld (conds @ conjuncts_s cond) then_branch o fld (conds @ s_not_conj [cond]) else_branch |
246 fld (conds @ conjuncts_s cond) then_branch o fld (conds @ s_not_conj [cond]) else_branch |
247 | (Const (c, _), args as _ :: _ :: _) => |
247 | (Const (c, _), args as _ :: _ :: _) => |
248 let val n = num_binder_types (Sign.the_const_type thy c) - 1 in |
248 let val n = num_binder_types (Sign.the_const_type thy c) - 1 in |
249 if n >= 0 andalso n < length args then |
249 if n >= 0 andalso n < length args then |
250 (case fastype_of1 (bound_Ts, nth args n) of |
250 (case fastype_of1 (bound_Ts, nth args n) of |
280 Abs (Name.uu, T, massage_abs (T :: bound_Ts) (m - 1) (incr_boundvars 1 t $ Bound 0)) |
280 Abs (Name.uu, T, massage_abs (T :: bound_Ts) (m - 1) (incr_boundvars 1 t $ Bound 0)) |
281 end |
281 end |
282 and massage_rec bound_Ts t = |
282 and massage_rec bound_Ts t = |
283 let val typof = curry fastype_of1 bound_Ts in |
283 let val typof = curry fastype_of1 bound_Ts in |
284 (case Term.strip_comb t of |
284 (case Term.strip_comb t of |
285 (Const (@{const_name Let}, _), [_, _]) => massage_rec bound_Ts (unfold_lets_splits t) |
285 (Const (\<^const_name>\<open>Let\<close>, _), [_, _]) => massage_rec bound_Ts (unfold_lets_splits t) |
286 | (Const (@{const_name If}, _), obj :: (branches as [_, _])) => |
286 | (Const (\<^const_name>\<open>If\<close>, _), obj :: (branches as [_, _])) => |
287 (case List.partition Term.is_dummy_pattern (map (massage_rec bound_Ts) branches) of |
287 (case List.partition Term.is_dummy_pattern (map (massage_rec bound_Ts) branches) of |
288 (dummy_branch' :: _, []) => dummy_branch' |
288 (dummy_branch' :: _, []) => dummy_branch' |
289 | (_, [branch']) => branch' |
289 | (_, [branch']) => branch' |
290 | (_, branches') => |
290 | (_, branches') => |
291 Term.list_comb (If_const (typof (hd branches')) $ tap (check_no_call bound_Ts) obj, |
291 Term.list_comb (If_const (typof (hd branches')) $ tap (check_no_call bound_Ts) obj, |
292 branches')) |
292 branches')) |
293 | (c as Const (@{const_name case_prod}, _), arg :: args) => |
293 | (c as Const (\<^const_name>\<open>case_prod\<close>, _), arg :: args) => |
294 massage_rec bound_Ts |
294 massage_rec bound_Ts |
295 (unfold_splits_lets (Term.list_comb (c $ Envir.eta_long bound_Ts arg, args))) |
295 (unfold_splits_lets (Term.list_comb (c $ Envir.eta_long bound_Ts arg, args))) |
296 | (Const (c, _), args as _ :: _ :: _) => |
296 | (Const (c, _), args as _ :: _ :: _) => |
297 (case try strip_fun_type (Sign.the_const_type thy c) of |
297 (case try strip_fun_type (Sign.the_const_type thy c) of |
298 SOME (gen_branch_Ts, gen_body_fun_T) => |
298 SOME (gen_branch_Ts, gen_body_fun_T) => |
331 | _ => massage_leaf bound_Ts t) |
331 | _ => massage_leaf bound_Ts t) |
332 end; |
332 end; |
333 in |
333 in |
334 massage_rec bound_Ts t0 |
334 massage_rec bound_Ts t0 |
335 |> Term.map_aterms (fn t => |
335 |> Term.map_aterms (fn t => |
336 if Term.is_dummy_pattern t then Const (@{const_name undefined}, fastype_of t) else t) |
336 if Term.is_dummy_pattern t then Const (\<^const_name>\<open>undefined\<close>, fastype_of t) else t) |
337 end; |
337 end; |
338 |
338 |
339 fun massage_let_if_case_corec ctxt has_call massage_leaf bound_Ts t0 = |
339 fun massage_let_if_case_corec ctxt has_call massage_leaf bound_Ts t0 = |
340 massage_let_if_case ctxt has_call massage_leaf (K (unexpected_corec_call_in ctxt [t0])) |
340 massage_let_if_case ctxt has_call massage_leaf (K (unexpected_corec_call_in ctxt [t0])) |
341 (K (unsupported_case_around_corec_call ctxt [t0])) bound_Ts t0; |
341 (K (unsupported_case_around_corec_call ctxt [t0])) bound_Ts t0; |
342 |
342 |
343 fun massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts U T t0 = |
343 fun massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts U T t0 = |
344 let |
344 let |
345 fun check_no_call t = if has_call t then unexpected_corec_call_in ctxt [t0] t else (); |
345 fun check_no_call t = if has_call t then unexpected_corec_call_in ctxt [t0] t else (); |
346 |
346 |
347 fun massage_mutual_call bound_Ts (Type (@{type_name fun}, [_, U2])) |
347 fun massage_mutual_call bound_Ts (Type (\<^type_name>\<open>fun\<close>, [_, U2])) |
348 (Type (@{type_name fun}, [T1, T2])) t = |
348 (Type (\<^type_name>\<open>fun\<close>, [T1, T2])) t = |
349 Abs (Name.uu, T1, massage_mutual_call (T1 :: bound_Ts) U2 T2 (incr_boundvars 1 t $ Bound 0)) |
349 Abs (Name.uu, T1, massage_mutual_call (T1 :: bound_Ts) U2 T2 (incr_boundvars 1 t $ Bound 0)) |
350 | massage_mutual_call bound_Ts U T t = |
350 | massage_mutual_call bound_Ts U T t = |
351 (if has_call t then massage_call else massage_noncall) bound_Ts U T t; |
351 (if has_call t then massage_call else massage_noncall) bound_Ts U T t; |
352 |
352 |
353 fun massage_map bound_Ts (Type (_, Us)) (Type (s, Ts)) t = |
353 fun massage_map bound_Ts (Type (_, Us)) (Type (s, Ts)) t = |
377 fun massage_body () = |
377 fun massage_body () = |
378 Term.lambda var (Term.incr_boundvars 1 (massage_any_call bound_Ts U T |
378 Term.lambda var (Term.incr_boundvars 1 (massage_any_call bound_Ts U T |
379 (betapply (t, var)))); |
379 (betapply (t, var)))); |
380 in |
380 in |
381 (case t of |
381 (case t of |
382 Const (@{const_name comp}, _) $ t1 $ t2 => |
382 Const (\<^const_name>\<open>comp\<close>, _) $ t1 $ t2 => |
383 if has_call t2 then massage_body () |
383 if has_call t2 then massage_body () |
384 else mk_comp bound_Ts (massage_mutual_fun bound_Ts U T t1, t2) |
384 else mk_comp bound_Ts (massage_mutual_fun bound_Ts U T t1, t2) |
385 | _ => massage_body ()) |
385 | _ => massage_body ()) |
386 end |
386 end |
387 and massage_any_call bound_Ts U T = |
387 and massage_any_call bound_Ts U T = |
400 Term.list_comb (f', |
400 Term.list_comb (f', |
401 @{map 3} (massage_any_call bound_Ts) (binder_types f'_T) arg_Ts args) |
401 @{map 3} (massage_any_call bound_Ts) (binder_types f'_T) arg_Ts args) |
402 end |
402 end |
403 | NONE => |
403 | NONE => |
404 (case t of |
404 (case t of |
405 Const (@{const_name case_prod}, _) $ t' => |
405 Const (\<^const_name>\<open>case_prod\<close>, _) $ t' => |
406 let |
406 let |
407 val U' = curried_type U; |
407 val U' = curried_type U; |
408 val T' = curried_type T; |
408 val T' = curried_type T; |
409 in |
409 in |
410 Const (@{const_name case_prod}, U' --> U) $ massage_any_call bound_Ts U' T' t' |
410 Const (\<^const_name>\<open>case_prod\<close>, U' --> U) $ massage_any_call bound_Ts U' T' t' |
411 end |
411 end |
412 | t1 $ t2 => |
412 | t1 $ t2 => |
413 (if has_call t2 then |
413 (if has_call t2 then |
414 massage_mutual_call bound_Ts U T t |
414 massage_mutual_call bound_Ts U T t |
415 else |
415 else |
553 val substAT = Term.typ_subst_TVars As_rho; |
553 val substAT = Term.typ_subst_TVars As_rho; |
554 val substCT = Term.typ_subst_TVars Cs_rho; |
554 val substCT = Term.typ_subst_TVars Cs_rho; |
555 |
555 |
556 val perm_Cs' = map substCT perm_Cs; |
556 val perm_Cs' = map substCT perm_Cs; |
557 |
557 |
558 fun call_of nullary [] [g_i] [Type (@{type_name fun}, [_, T])] = |
558 fun call_of nullary [] [g_i] [Type (\<^type_name>\<open>fun\<close>, [_, T])] = |
559 (if exists_subtype_in Cs T then Nested_Corec |
559 (if exists_subtype_in Cs T then Nested_Corec |
560 else if nullary then Dummy_No_Corec |
560 else if nullary then Dummy_No_Corec |
561 else No_Corec) g_i |
561 else No_Corec) g_i |
562 | call_of _ [q_i] [g_i, g_i'] _ = Mutual_Corec (q_i, g_i, g_i'); |
562 | call_of _ [q_i] [g_i, g_i'] _ = Mutual_Corec (q_i, g_i, g_i'); |
563 |
563 |
593 co_induct_of common_coinduct_thms, strong_co_induct_of common_coinduct_thms, |
593 co_induct_of common_coinduct_thms, strong_co_induct_of common_coinduct_thms, |
594 co_induct_of coinduct_thmss, strong_co_induct_of coinduct_thmss, coinduct_attrs_pair, |
594 co_induct_of coinduct_thmss, strong_co_induct_of coinduct_thmss, coinduct_attrs_pair, |
595 is_some gfp_sugar_thms, lthy) |
595 is_some gfp_sugar_thms, lthy) |
596 end; |
596 end; |
597 |
597 |
598 val undef_const = Const (@{const_name undefined}, dummyT); |
598 val undef_const = Const (\<^const_name>\<open>undefined\<close>, dummyT); |
599 |
599 |
600 type coeqn_data_disc = |
600 type coeqn_data_disc = |
601 {fun_name: string, |
601 {fun_name: string, |
602 fun_T: typ, |
602 fun_T: typ, |
603 fun_args: term list, |
603 fun_args: term list, |
674 val (sequential, basic_ctr_specs) = |
674 val (sequential, basic_ctr_specs) = |
675 the (AList.lookup (op =) (fun_names ~~ (sequentials ~~ basic_ctr_specss)) fun_name); |
675 the (AList.lookup (op =) (fun_names ~~ (sequentials ~~ basic_ctr_specss)) fun_name); |
676 |
676 |
677 val discs = map #disc basic_ctr_specs; |
677 val discs = map #disc basic_ctr_specs; |
678 val ctrs = map #ctr basic_ctr_specs; |
678 val ctrs = map #ctr basic_ctr_specs; |
679 val not_disc = head_of concl = @{term Not}; |
679 val not_disc = head_of concl = \<^term>\<open>Not\<close>; |
680 val _ = not_disc andalso length ctrs <> 2 andalso |
680 val _ = not_disc andalso length ctrs <> 2 andalso |
681 error_at ctxt [concl] "Negated discriminator for a type with \<noteq> 2 constructors"; |
681 error_at ctxt [concl] "Negated discriminator for a type with \<noteq> 2 constructors"; |
682 val disc' = find_subterm (member (op =) discs o head_of) concl; |
682 val disc' = find_subterm (member (op =) discs o head_of) concl; |
683 val eq_ctr0 = concl |> perhaps (try HOLogic.dest_not) |> try (HOLogic.dest_eq #> snd) |
683 val eq_ctr0 = concl |> perhaps (try HOLogic.dest_not) |> try (HOLogic.dest_eq #> snd) |
684 |> (fn SOME t => let val n = find_index (curry (op =) t) ctrs in |
684 |> (fn SOME t => let val n = find_index (curry (op =) t) ctrs in |
892 NONE => (I, I, I) |
892 NONE => (I, I, I) |
893 | SOME {fun_args, rhs_term, ... } => |
893 | SOME {fun_args, rhs_term, ... } => |
894 let |
894 let |
895 val bound_Ts = List.rev (map fastype_of fun_args); |
895 val bound_Ts = List.rev (map fastype_of fun_args); |
896 |
896 |
897 fun rewrite_stop _ t = if has_call t then @{term False} else @{term True}; |
897 fun rewrite_stop _ t = if has_call t then \<^term>\<open>False\<close> else \<^term>\<open>True\<close>; |
898 fun rewrite_end _ t = if has_call t then undef_const else t; |
898 fun rewrite_end _ t = if has_call t then undef_const else t; |
899 fun rewrite_cont bound_Ts t = |
899 fun rewrite_cont bound_Ts t = |
900 if has_call t then mk_tuple1_balanced bound_Ts (snd (strip_comb t)) else undef_const; |
900 if has_call t then mk_tuple1_balanced bound_Ts (snd (strip_comb t)) else undef_const; |
901 fun massage f _ = massage_let_if_case_corec ctxt has_call f bound_Ts rhs_term |
901 fun massage f _ = massage_let_if_case_corec ctxt has_call f bound_Ts rhs_term |
902 |> abs_tuple_balanced fun_args; |
902 |> abs_tuple_balanced fun_args; |
919 fun rewrite bound_Ts (Abs (s, T', t')) = Abs (s, T', rewrite (T' :: bound_Ts) t') |
919 fun rewrite bound_Ts (Abs (s, T', t')) = Abs (s, T', rewrite (T' :: bound_Ts) t') |
920 | rewrite bound_Ts (t as _ $ _) = |
920 | rewrite bound_Ts (t as _ $ _) = |
921 let val (u, vs) = strip_comb t in |
921 let val (u, vs) = strip_comb t in |
922 if is_Free u andalso has_call u then |
922 if is_Free u andalso has_call u then |
923 Inr_const T U2 $ mk_tuple1_balanced bound_Ts vs |
923 Inr_const T U2 $ mk_tuple1_balanced bound_Ts vs |
924 else if try (fst o dest_Const) u = SOME @{const_name case_prod} then |
924 else if try (fst o dest_Const) u = SOME \<^const_name>\<open>case_prod\<close> then |
925 map (rewrite bound_Ts) vs |> chop 1 |
925 map (rewrite bound_Ts) vs |> chop 1 |
926 |>> HOLogic.mk_case_prod o the_single |
926 |>> HOLogic.mk_case_prod o the_single |
927 |> Term.list_comb |
927 |> Term.list_comb |
928 else |
928 else |
929 Term.list_comb (rewrite bound_Ts u, map (rewrite bound_Ts) vs) |
929 Term.list_comb (rewrite bound_Ts u, map (rewrite bound_Ts) vs) |
972 val corecs = map #corec corec_specs; |
972 val corecs = map #corec corec_specs; |
973 val ctr_specss = map #ctr_specs corec_specs; |
973 val ctr_specss = map #ctr_specs corec_specs; |
974 val corec_args = hd corecs |
974 val corec_args = hd corecs |
975 |> fst o split_last o binder_types o fastype_of |
975 |> fst o split_last o binder_types o fastype_of |
976 |> map (fn T => |
976 |> map (fn T => |
977 if range_type T = HOLogic.boolT then Abs (Name.uu_, domain_type T, @{term False}) |
977 if range_type T = HOLogic.boolT then Abs (Name.uu_, domain_type T, \<^term>\<open>False\<close>) |
978 else Const (@{const_name undefined}, T)) |
978 else Const (\<^const_name>\<open>undefined\<close>, T)) |
979 |> fold2 (fold o build_corec_arg_disc) ctr_specss disc_eqnss |
979 |> fold2 (fold o build_corec_arg_disc) ctr_specss disc_eqnss |
980 |> fold2 (fold o build_corec_args_sel ctxt has_call) sel_eqnss ctr_specss; |
980 |> fold2 (fold o build_corec_args_sel ctxt has_call) sel_eqnss ctr_specss; |
981 |
981 |
982 val bad = fold (add_extra_frees ctxt [] []) corec_args []; |
982 val bad = fold (add_extra_frees ctxt [] []) corec_args []; |
983 val _ = null bad orelse |
983 val _ = null bad orelse |
1243 map2 (fn excludes => mk_excludesss excludes o length o #ctr_specs) |
1243 map2 (fn excludes => mk_excludesss excludes o length o #ctr_specs) |
1244 (map2 append excludess' taut_thmss) corec_specs; |
1244 (map2 append excludess' taut_thmss) corec_specs; |
1245 |
1245 |
1246 fun prove_disc ({ctr_specs, ...} : corec_spec) excludesss |
1246 fun prove_disc ({ctr_specs, ...} : corec_spec) excludesss |
1247 ({fun_name, fun_T, fun_args, ctr_no, prems, eqn_pos, ...} : coeqn_data_disc) = |
1247 ({fun_name, fun_T, fun_args, ctr_no, prems, eqn_pos, ...} : coeqn_data_disc) = |
1248 if Term.aconv_untyped (#disc (nth ctr_specs ctr_no), @{term "\<lambda>x. x = x"}) then |
1248 if Term.aconv_untyped (#disc (nth ctr_specs ctr_no), \<^term>\<open>\<lambda>x. x = x\<close>) then |
1249 [] |
1249 [] |
1250 else |
1250 else |
1251 let |
1251 let |
1252 val {disc, corec_disc, ...} = nth ctr_specs ctr_no; |
1252 val {disc, corec_disc, ...} = nth ctr_specs ctr_no; |
1253 val k = 1 + ctr_no; |
1253 val k = 1 + ctr_no; |
1257 |> curry betapply disc |
1257 |> curry betapply disc |
1258 |> HOLogic.mk_Trueprop |
1258 |> HOLogic.mk_Trueprop |
1259 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1259 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1260 |> curry Logic.list_all (map dest_Free fun_args); |
1260 |> curry Logic.list_all (map dest_Free fun_args); |
1261 in |
1261 in |
1262 if prems = [@{term False}] then |
1262 if prems = [\<^term>\<open>False\<close>] then |
1263 [] |
1263 [] |
1264 else |
1264 else |
1265 Goal.prove_sorry lthy [] [] goal |
1265 Goal.prove_sorry lthy [] [] goal |
1266 (fn {context = ctxt, prems = _} => |
1266 (fn {context = ctxt, prems = _} => |
1267 mk_primcorec_disc_tac ctxt def_thms corec_disc k m excludesss) |
1267 mk_primcorec_disc_tac ctxt def_thms corec_disc k m excludesss) |
1339 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1339 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1340 |> curry Logic.list_all (map dest_Free fun_args); |
1340 |> curry Logic.list_all (map dest_Free fun_args); |
1341 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1341 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1342 val sel_thms = map (snd o snd) (filter (member (op =) sels o fst) sel_alist); |
1342 val sel_thms = map (snd o snd) (filter (member (op =) sels o fst) sel_alist); |
1343 in |
1343 in |
1344 if prems = [@{term False}] then |
1344 if prems = [\<^term>\<open>False\<close>] then |
1345 [] |
1345 [] |
1346 else |
1346 else |
1347 Goal.prove_sorry lthy [] [] goal |
1347 Goal.prove_sorry lthy [] [] goal |
1348 (fn {context = ctxt, prems = _} => |
1348 (fn {context = ctxt, prems = _} => |
1349 mk_primcorec_ctr_tac ctxt m collapse disc_thm_opt sel_thms) |
1349 mk_primcorec_ctr_tac ctxt m collapse disc_thm_opt sel_thms) |
1407 andalso exists #auto_gen disc_eqns; |
1407 andalso exists #auto_gen disc_eqns; |
1408 val rhs = |
1408 val rhs = |
1409 (if exhaustive_code then |
1409 (if exhaustive_code then |
1410 split_last (map_filter I ctr_conds_argss_opt) ||> snd |
1410 split_last (map_filter I ctr_conds_argss_opt) ||> snd |
1411 else |
1411 else |
1412 Const (@{const_name Code.abort}, @{typ String.literal} --> |
1412 Const (\<^const_name>\<open>Code.abort\<close>, \<^typ>\<open>String.literal\<close> --> |
1413 (HOLogic.unitT --> body_type fun_T) --> body_type fun_T) $ |
1413 (HOLogic.unitT --> body_type fun_T) --> body_type fun_T) $ |
1414 HOLogic.mk_literal fun_name $ |
1414 HOLogic.mk_literal fun_name $ |
1415 absdummy HOLogic.unitT (incr_boundvars 1 lhs) |
1415 absdummy HOLogic.unitT (incr_boundvars 1 lhs) |
1416 |> pair (map_filter I ctr_conds_argss_opt)) |
1416 |> pair (map_filter I ctr_conds_argss_opt)) |
1417 |-> fold_rev (fn (prems, u) => mk_If (s_conjs prems) u) |
1417 |-> fold_rev (fn (prems, u) => mk_If (s_conjs prems) u) |
1585 || Parse.reserved "transfer" >> K Transfer_Option); |
1585 || Parse.reserved "transfer" >> K Transfer_Option); |
1586 |
1586 |
1587 val where_alt_props_of_parser = Parse.where_ |-- Parse.!!! (Parse.enum1 "|" |
1587 val where_alt_props_of_parser = Parse.where_ |-- Parse.!!! (Parse.enum1 "|" |
1588 ((Parse.prop >> pair Binding.empty_atts) -- Scan.option (Parse.reserved "of" |-- Parse.const))); |
1588 ((Parse.prop >> pair Binding.empty_atts) -- Scan.option (Parse.reserved "of" |-- Parse.const))); |
1589 |
1589 |
1590 val _ = Outer_Syntax.local_theory_to_proof @{command_keyword primcorecursive} |
1590 val _ = Outer_Syntax.local_theory_to_proof \<^command_keyword>\<open>primcorecursive\<close> |
1591 "define primitive corecursive functions" |
1591 "define primitive corecursive functions" |
1592 ((Scan.optional (@{keyword "("} |-- |
1592 ((Scan.optional (\<^keyword>\<open>(\<close> |-- |
1593 Parse.!!! (Parse.list1 corec_option_parser) --| @{keyword ")"}) []) -- |
1593 Parse.!!! (Parse.list1 corec_option_parser) --| \<^keyword>\<open>)\<close>) []) -- |
1594 (Parse.vars -- where_alt_props_of_parser) >> uncurry (primcorecursive_cmd true)); |
1594 (Parse.vars -- where_alt_props_of_parser) >> uncurry (primcorecursive_cmd true)); |
1595 |
1595 |
1596 val _ = Outer_Syntax.local_theory @{command_keyword primcorec} |
1596 val _ = Outer_Syntax.local_theory \<^command_keyword>\<open>primcorec\<close> |
1597 "define primitive corecursive functions" |
1597 "define primitive corecursive functions" |
1598 ((Scan.optional (@{keyword "("} |-- Parse.!!! (Parse.list1 corec_option_parser) |
1598 ((Scan.optional (\<^keyword>\<open>(\<close> |-- Parse.!!! (Parse.list1 corec_option_parser) |
1599 --| @{keyword ")"}) []) -- |
1599 --| \<^keyword>\<open>)\<close>) []) -- |
1600 (Parse.vars -- where_alt_props_of_parser) >> uncurry (primcorec_cmd true)); |
1600 (Parse.vars -- where_alt_props_of_parser) >> uncurry (primcorec_cmd true)); |
1601 |
1601 |
1602 val _ = Theory.setup (gfp_rec_sugar_interpretation transfer_plugin |
1602 val _ = Theory.setup (gfp_rec_sugar_interpretation transfer_plugin |
1603 gfp_rec_sugar_transfer_interpretation); |
1603 gfp_rec_sugar_transfer_interpretation); |
1604 |
1604 |