534 end; |
534 end; |
535 |
535 |
536 fun build_corec_args_discs disc_eqns ctr_specs = |
536 fun build_corec_args_discs disc_eqns ctr_specs = |
537 if null disc_eqns then I else |
537 if null disc_eqns then I else |
538 let |
538 let |
|
539 (*val _ = tracing ("d/p:\<cdot> " ^ space_implode "\n \<cdot> " (map ((op ^) o |
|
540 apfst (Syntax.string_of_term @{context}) o apsnd (curry (op ^) " / " o @{make_string})) |
|
541 (ctr_specs |> map_filter (fn {disc, pred = SOME pred, ...} => SOME (disc, pred) | _ => NONE))));*) |
539 val conds = map #cond disc_eqns; |
542 val conds = map #cond disc_eqns; |
540 val fun_args = #fun_args (hd disc_eqns); |
543 val fun_args = #fun_args (hd disc_eqns); |
541 val args = |
544 val args = |
542 if length ctr_specs = 1 then [] |
545 if length ctr_specs = 1 then [] |
543 else if length disc_eqns = length ctr_specs then |
546 else if length disc_eqns = length ctr_specs then |
544 fst (split_last conds) |
547 fst (split_last conds) |
545 else if length disc_eqns = length ctr_specs - 1 then |
548 else if length disc_eqns = length ctr_specs - 1 then |
546 let val n = 0 upto length ctr_specs - 1 |
549 let val n = 0 upto length ctr_specs - 1 |
547 |> the o find_first (fn idx => not (exists (equal idx o #ctr_no) disc_eqns)) (*###*) in |
550 |> the(*###*) o find_first (fn idx => not (exists (equal idx o #ctr_no) disc_eqns)) in |
548 if n = length ctr_specs - 1 then |
551 if n = length ctr_specs - 1 then |
549 conds |
552 conds |
550 else |
553 else |
551 split_last conds |
554 split_last conds |
552 ||> HOLogic.mk_not |
555 ||> HOLogic.mk_not |
553 |>> chop n |
556 |> `(uncurry (fold (curry HOLogic.mk_conj o HOLogic.mk_not))) |
554 |> (fn ((l, r), x) => l @ (x :: r)) |
557 ||> chop n o fst |
|
558 |> (fn (x, (l, r)) => l @ (x :: r)) |
555 end |
559 end |
556 else |
560 else |
557 0 upto length ctr_specs - 1 |
561 0 upto length ctr_specs - 1 |
558 |> map (fn idx => find_first (equal idx o #ctr_no) disc_eqns |
562 |> map (fn idx => find_first (equal idx o #ctr_no) disc_eqns |
559 |> Option.map #cond |
563 |> Option.map #cond |
568 end; |
572 end; |
569 |
573 |
570 fun build_corec_arg_no_call sel_eqns sel = find_first (equal sel o #sel) sel_eqns |
574 fun build_corec_arg_no_call sel_eqns sel = find_first (equal sel o #sel) sel_eqns |
571 |> try (fn SOME sel_eqn => (#fun_args sel_eqn, #rhs_term sel_eqn)) |
575 |> try (fn SOME sel_eqn => (#fun_args sel_eqn, #rhs_term sel_eqn)) |
572 |> the_default ([], undef_const) |
576 |> the_default ([], undef_const) |
573 |-> abs_tuple; |
577 |-> abs_tuple |
|
578 |> K; |
574 |
579 |
575 fun build_corec_arg_direct_call lthy has_call sel_eqns sel = |
580 fun build_corec_arg_direct_call lthy has_call sel_eqns sel = |
576 let |
581 let |
577 val maybe_sel_eqn = find_first (equal sel o #sel) sel_eqns |
582 val maybe_sel_eqn = find_first (equal sel o #sel) sel_eqns; |
578 fun rewrite is_end U T t = |
583 fun rewrite is_end U T t = |
579 if U = @{typ bool} then @{term True} |> has_call t ? K @{term False} (* stop? *) |
584 if U = @{typ bool} then @{term True} |> has_call t ? K @{term False} (* stop? *) |
580 else if is_end = has_call t then undef_const |
585 else if is_end = has_call t then undef_const |
581 else if is_end then t (* end *) |
586 else if is_end then t (* end *) |
582 else HOLogic.mk_tuple (snd (strip_comb t)); (* continue *) |
587 else HOLogic.mk_tuple (snd (strip_comb t)); (* continue *) |
585 in |
590 in |
586 if is_none maybe_sel_eqn then K I else |
591 if is_none maybe_sel_eqn then K I else |
587 abs_tuple (#fun_args (the maybe_sel_eqn)) oo massage (#rhs_term (the maybe_sel_eqn)) |
592 abs_tuple (#fun_args (the maybe_sel_eqn)) oo massage (#rhs_term (the maybe_sel_eqn)) |
588 end; |
593 end; |
589 |
594 |
590 fun build_corec_arg_indirect_call sel_eqns sel = |
595 fun build_corec_arg_indirect_call lthy has_call sel_eqns sel = |
591 primrec_error "indirect corecursion not implemented yet"; |
596 let |
|
597 val maybe_sel_eqn = find_first (equal sel o #sel) sel_eqns; |
|
598 fun rewrite _ _ = |
|
599 let |
|
600 fun subst (Abs (v, T, b)) = Abs (v, T, subst b) |
|
601 | subst (t as _ $ _) = |
|
602 let val (u, vs) = strip_comb t in |
|
603 if is_Free u andalso has_call u then |
|
604 Const (@{const_name Inr}, dummyT) $ (*HOLogic.mk_tuple vs*) |
|
605 (try (foldr1 (fn (x, y) => Const (@{const_name Pair}, dummyT) $ x $ y)) vs |
|
606 |> the_default (hd vs)) |
|
607 else if try (fst o dest_Const) u = SOME @{const_name prod_case} then |
|
608 list_comb (u |> map_types (K dummyT), map subst vs) |
|
609 else |
|
610 list_comb (subst u, map subst vs) |
|
611 end |
|
612 | subst t = t; |
|
613 in |
|
614 subst |
|
615 end; |
|
616 fun massage rhs_term t = massage_indirect_corec_call |
|
617 lthy has_call rewrite [] (fastype_of t |> range_type) rhs_term; |
|
618 in |
|
619 if is_none maybe_sel_eqn then I else |
|
620 abs_tuple (#fun_args (the maybe_sel_eqn)) o massage (#rhs_term (the maybe_sel_eqn)) |
|
621 end; |
592 |
622 |
593 fun build_corec_args_sel lthy has_call all_sel_eqns ctr_spec = |
623 fun build_corec_args_sel lthy has_call all_sel_eqns ctr_spec = |
594 let val sel_eqns = filter (equal (#ctr ctr_spec) o #ctr) all_sel_eqns in |
624 let val sel_eqns = filter (equal (#ctr ctr_spec) o #ctr) all_sel_eqns in |
595 if null sel_eqns then I else |
625 if null sel_eqns then I else |
596 let |
626 let |
597 val sel_call_list = #sels ctr_spec ~~ #calls ctr_spec; |
627 val sel_call_list = #sels ctr_spec ~~ #calls ctr_spec; |
598 |
628 |
599 val _ = tracing ("sels / calls:\n \<cdot> " ^ space_implode "\n \<cdot> " (map ((op ^) o |
629 (*val _ = tracing ("s/c:\<cdot> " ^ space_implode "\n \<cdot> " (map ((op ^) o |
600 apfst (Syntax.string_of_term @{context}) o apsnd (curry (op ^) " / " o @{make_string})) |
630 apfst (Syntax.string_of_term lthy) o apsnd (curry (op ^) " / " o @{make_string})) |
601 (sel_call_list))); |
631 sel_call_list));*) |
602 |
632 |
603 val no_calls' = map_filter (try (apsnd (fn No_Corec n => n))) sel_call_list; |
633 val no_calls' = map_filter (try (apsnd (fn No_Corec n => n))) sel_call_list; |
604 val direct_calls' = map_filter (try (apsnd (fn Direct_Corec n => n))) sel_call_list; |
634 val direct_calls' = map_filter (try (apsnd (fn Direct_Corec n => n))) sel_call_list; |
605 val indirect_calls' = map_filter (try (apsnd (fn Indirect_Corec n => n))) sel_call_list; |
635 val indirect_calls' = map_filter (try (apsnd (fn Indirect_Corec n => n))) sel_call_list; |
606 in |
636 in |
607 I |
637 I |
608 #> fold (fn (sel, n) => nth_map n |
638 #> fold (fn (sel, n) => nth_map n |
609 (build_corec_arg_no_call sel_eqns sel |> K)) no_calls' |
639 (build_corec_arg_no_call sel_eqns sel)) no_calls' |
610 #> fold (fn (sel, (q, g, h)) => |
640 #> fold (fn (sel, (q, g, h)) => |
611 let val f = build_corec_arg_direct_call lthy has_call sel_eqns sel in |
641 let val f = build_corec_arg_direct_call lthy has_call sel_eqns sel in |
612 nth_map h (f false) o nth_map g (f true) o nth_map q (f true) end) direct_calls' |
642 nth_map h (f false) o nth_map g (f true) o nth_map q (f true) end) direct_calls' |
613 #> fold (fn (sel, n) => nth_map n |
643 #> fold (fn (sel, n) => nth_map n |
614 (build_corec_arg_indirect_call sel_eqns sel |> K)) indirect_calls' |
644 (build_corec_arg_indirect_call lthy has_call sel_eqns sel)) indirect_calls' |
615 end |
645 end |
616 end; |
646 end; |
617 |
647 |
618 fun co_build_defs lthy sequential bs mxs has_call arg_Tss fun_name_corec_spec_list eqns_data = |
648 fun co_build_defs lthy sequential bs mxs has_call arg_Tss fun_name_corec_spec_list eqns_data = |
619 let |
649 let |
650 t $ foldr1 (fn (u, v) => HOLogic.pair_const dummyT dummyT $ u $ v) |
680 t $ foldr1 (fn (u, v) => HOLogic.pair_const dummyT dummyT $ u $ v) |
651 (length Ts - 1 downto 0 |> map Bound) |
681 (length Ts - 1 downto 0 |> map Bound) |
652 |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts; |
682 |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts; |
653 |
683 |
654 val _ = tracing ("corecursor arguments:\n \<cdot> " ^ |
684 val _ = tracing ("corecursor arguments:\n \<cdot> " ^ |
655 space_implode "\n \<cdot> " (map (Syntax.string_of_term @{context}) corec_args)); |
685 space_implode "\n \<cdot> " (map (Syntax.string_of_term lthy) corec_args)); |
656 |
686 |
657 fun uneq_pairs_rev xs = xs (* FIXME \<exists>? *) |
687 fun uneq_pairs_rev xs = xs (* FIXME \<exists>? *) |
658 |> these o try (split_last #> (fn (ys, y) => uneq_pairs_rev ys @ map (pair y) ys)); |
688 |> these o try (split_last #> (fn (ys, y) => uneq_pairs_rev ys @ map (pair y) ys)); |
659 val proof_obligations = if sequential then [] else |
689 val proof_obligations = if sequential then [] else |
660 maps (uneq_pairs_rev o map (fn {fun_args, cond, ...} => (fun_args, cond))) disc_eqnss |
690 disc_eqnss |
|
691 |> maps (uneq_pairs_rev o map (fn {fun_args, cond, ...} => (fun_args, cond))) |
661 |> map (fn ((fun_args, x), (_, y)) => [x, HOLogic.mk_not y] |
692 |> map (fn ((fun_args, x), (_, y)) => [x, HOLogic.mk_not y] |
662 |> map (HOLogic.mk_Trueprop o curry subst_bounds (List.rev fun_args)) |
693 |> map (HOLogic.mk_Trueprop o curry subst_bounds (List.rev fun_args)) |
663 |> curry list_comb @{const ==>}); |
694 |> curry list_comb @{const ==>}); |
664 |
695 |
665 val _ = tracing ("proof obligations:\n \<cdot> " ^ |
696 val _ = tracing ("proof obligations:\n \<cdot> " ^ |
666 space_implode "\n \<cdot> " (map (Syntax.string_of_term @{context}) proof_obligations)); |
697 space_implode "\n \<cdot> " (map (Syntax.string_of_term lthy) proof_obligations)); |
667 |
698 |
668 in |
699 in |
669 map (list_comb o rpair corec_args) corecs |
700 map (list_comb o rpair corec_args) corecs |
670 |> map2 (fn Ts => fn t => if length Ts = 0 then t $ HOLogic.unit else t) arg_Tss |
701 |> map2 (fn Ts => fn t => if length Ts = 0 then t $ HOLogic.unit else t) arg_Tss |
671 |> map2 currys arg_Tss |
702 |> map2 currys arg_Tss |