393 (case fast_string_ord (s1, s2) of |
393 (case fast_string_ord (s1, s2) of |
394 EQUAL => Term_Ord.typ_ord (T1, T2) |
394 EQUAL => Term_Ord.typ_ord (T1, T2) |
395 | ord => ord) |
395 | ord => ord) |
396 | name_ord (u1, u2) = raise NUT ("Nitpick_Nut.name_ord", [u1, u2]) |
396 | name_ord (u1, u2) = raise NUT ("Nitpick_Nut.name_ord", [u1, u2]) |
397 |
397 |
398 fun num_occs_in_nut needle_u stack_u = |
398 fun num_occurrences_in_nut needle_u stack_u = |
399 fold_nut (fn u => if u = needle_u then Integer.add 1 else I) stack_u 0 |
399 fold_nut (fn u => if u = needle_u then Integer.add 1 else I) stack_u 0 |
400 val is_subterm_of = not_equal 0 oo num_occs_in_nut |
400 val is_subnut_of = not_equal 0 oo num_occurrences_in_nut |
401 |
401 |
402 fun substitute_in_nut needle_u needle_u' = |
402 fun substitute_in_nut needle_u needle_u' = |
403 map_nut (fn u => if u = needle_u then needle_u' else u) |
403 map_nut (fn u => if u = needle_u then needle_u' else u) |
404 |
404 |
405 val add_free_and_const_names = |
405 val add_free_and_const_names = |
470 end |
470 end |
471 fun do_quantifier quant s T t1 = |
471 fun do_quantifier quant s T t1 = |
472 let |
472 let |
473 val bound_u = BoundName (length Ts, T, Any, s) |
473 val bound_u = BoundName (length Ts, T, Any, s) |
474 val body_u = sub_abs s T t1 |
474 val body_u = sub_abs s T t1 |
475 in |
475 in Op2 (quant, bool_T, Any, bound_u, body_u) end |
476 if is_subterm_of bound_u body_u then |
|
477 Op2 (quant, bool_T, Any, bound_u, body_u) |
|
478 else |
|
479 body_u |
|
480 end |
|
481 fun do_apply t0 ts = |
476 fun do_apply t0 ts = |
482 let |
477 let |
483 val (ts', t2) = split_last ts |
478 val (ts', t2) = split_last ts |
484 val t1 = list_comb (t0, ts') |
479 val t1 = list_comb (t0, ts') |
485 val T1 = fastype_of1 (Ts, t1) |
480 val T1 = fastype_of1 (Ts, t1) |
747 let val R = best_one_rep_for_type scope (type_of v) in |
742 let val R = best_one_rep_for_type scope (type_of v) in |
748 NameTable.update (v, R) table |
743 NameTable.update (v, R) table |
749 end |
744 end |
750 |
745 |
751 (* A nut is said to be constructive if whenever it evaluates to unknown in our |
746 (* A nut is said to be constructive if whenever it evaluates to unknown in our |
752 three-valued logic, it would evaluate to a unrepresentable value ("Unrep") |
747 three-valued logic, it would evaluate to an unrepresentable value ("Unrep") |
753 according to the HOL semantics. For example, "Suc n" is constructive if "n" |
748 according to the HOL semantics. For example, "Suc n" is constructive if "n" |
754 is representable or "Unrep", because unknown implies "Unrep". *) |
749 is representable or "Unrep", because unknown implies "Unrep". *) |
755 fun is_constructive u = |
750 fun is_constructive u = |
756 is_Cst Unrep u orelse |
751 is_Cst Unrep u orelse |
757 (not (is_fun_type (type_of u)) andalso not (is_opt_rep (rep_of u))) orelse |
752 (not (is_fun_type (type_of u)) andalso not (is_opt_rep (rep_of u))) orelse |
774 fun is_fully_representable_set u = |
769 fun is_fully_representable_set u = |
775 not (is_opt_rep (rep_of u)) andalso |
770 not (is_opt_rep (rep_of u)) andalso |
776 case u of |
771 case u of |
777 FreeName _ => true |
772 FreeName _ => true |
778 | Op1 (SingletonSet, _, _, _) => true |
773 | Op1 (SingletonSet, _, _, _) => true |
|
774 | Op1 (Converse, _, _, u1) => is_fully_representable_set u1 |
779 | Op2 (oper, _, _, u1, u2) => |
775 | Op2 (oper, _, _, u1, u2) => |
780 member (op =) [Union, SetDifference, Intersect] oper andalso |
776 if oper = Union orelse oper = SetDifference orelse oper = Intersect then |
781 forall is_fully_representable_set [u1, u2] |
777 forall is_fully_representable_set [u1, u2] |
|
778 else if oper = Apply then |
|
779 case u1 of |
|
780 ConstName (s, _, _) => is_sel_like_and_no_discr s |
|
781 | _ => false |
|
782 else |
|
783 false |
782 | _ => false |
784 | _ => false |
783 |
785 |
784 fun s_op1 oper T R u1 = |
786 fun s_op1 oper T R u1 = |
785 ((if oper = Not then |
787 ((if oper = Not then |
786 if is_Cst True u1 then Cst (False, T, R) |
788 if is_Cst True u1 then Cst (False, T, R) |
790 raise SAME ()) |
792 raise SAME ()) |
791 handle SAME () => Op1 (oper, T, R, u1)) |
793 handle SAME () => Op1 (oper, T, R, u1)) |
792 |> optimize_unit |
794 |> optimize_unit |
793 fun s_op2 oper T R u1 u2 = |
795 fun s_op2 oper T R u1 u2 = |
794 ((case oper of |
796 ((case oper of |
795 Or => |
797 All => if is_subnut_of u1 u2 then Op2 (All, T, R, u1, u2) else u2 |
|
798 | Exist => if is_subnut_of u1 u2 then Op2 (Exist, T, R, u1, u2) else u2 |
|
799 | Or => |
796 if exists (is_Cst True) [u1, u2] then Cst (True, T, unopt_rep R) |
800 if exists (is_Cst True) [u1, u2] then Cst (True, T, unopt_rep R) |
797 else if is_Cst False u1 then u2 |
801 else if is_Cst False u1 then u2 |
798 else if is_Cst False u2 then u1 |
802 else if is_Cst False u2 then u1 |
799 else raise SAME () |
803 else raise SAME () |
800 | And => |
804 | And => |
814 else raise SAME () |
818 else raise SAME () |
815 | Apply => |
819 | Apply => |
816 if is_Cst Unrep u1 then |
820 if is_Cst Unrep u1 then |
817 Cst (Unrep, T, R) |
821 Cst (Unrep, T, R) |
818 else if is_Cst Unrep u2 then |
822 else if is_Cst Unrep u2 then |
819 if is_constructive u1 then |
823 if is_boolean_type T then |
820 Cst (Unrep, T, R) |
|
821 else if is_boolean_type T then |
|
822 if is_fully_representable_set u1 then Cst (False, T, Formula Neut) |
824 if is_fully_representable_set u1 then Cst (False, T, Formula Neut) |
823 else unknown_boolean T R |
825 else unknown_boolean T R |
|
826 else if is_constructive u1 then |
|
827 Cst (Unrep, T, R) |
824 else case u1 of |
828 else case u1 of |
825 Op2 (Apply, _, _, ConstName (@{const_name List.append}, _, _), _) => |
829 Op2 (Apply, _, _, ConstName (@{const_name List.append}, _, _), _) => |
826 Cst (Unrep, T, R) |
830 Cst (Unrep, T, R) |
827 | _ => raise SAME () |
831 | _ => raise SAME () |
828 else |
832 else |
831 handle SAME () => Op2 (oper, T, R, u1, u2)) |
835 handle SAME () => Op2 (oper, T, R, u1, u2)) |
832 |> optimize_unit |
836 |> optimize_unit |
833 fun s_op3 oper T R u1 u2 u3 = |
837 fun s_op3 oper T R u1 u2 u3 = |
834 ((case oper of |
838 ((case oper of |
835 Let => |
839 Let => |
836 if inline_nut u2 orelse num_occs_in_nut u1 u3 < 2 then |
840 if inline_nut u2 orelse num_occurrences_in_nut u1 u3 < 2 then |
837 substitute_in_nut u1 u2 u3 |
841 substitute_in_nut u1 u2 u3 |
838 else |
842 else |
839 raise SAME () |
843 raise SAME () |
840 | _ => raise SAME ()) |
844 | _ => raise SAME ()) |
841 handle SAME () => Op3 (oper, T, R, u1, u2, u3)) |
845 handle SAME () => Op3 (oper, T, R, u1, u2, u3)) |
842 |> optimize_unit |
846 |> optimize_unit |
843 fun s_tuple T R us = |
847 fun s_tuple T R us = |
844 (if exists (is_Cst Unrep) us then Cst (Unrep, T, R) else Tuple (T, R, us)) |
848 (if exists (is_Cst Unrep) us then Cst (Unrep, T, R) else Tuple (T, R, us)) |
845 |> optimize_unit |
849 |> optimize_unit |
846 |
|
847 fun optimize_nut u = |
|
848 case u of |
|
849 Op1 (oper, T, R, u1) => s_op1 oper T R (optimize_nut u1) |
|
850 | Op2 (oper, T, R, u1, u2) => |
|
851 s_op2 oper T R (optimize_nut u1) (optimize_nut u2) |
|
852 | Op3 (oper, T, R, u1, u2, u3) => |
|
853 s_op3 oper T R (optimize_nut u1) (optimize_nut u2) (optimize_nut u3) |
|
854 | Tuple (T, R, us) => s_tuple T R (map optimize_nut us) |
|
855 | Construct (us', T, R, us) => Construct (us', T, R, map optimize_nut us) |
|
856 | _ => optimize_unit u |
|
857 |
850 |
858 fun untuple f (Tuple (_, _, us)) = maps (untuple f) us |
851 fun untuple f (Tuple (_, _, us)) = maps (untuple f) us |
859 | untuple f u = if rep_of u = Unit then [] else [f u] |
852 | untuple f u = if rep_of u = Unit then [] else [f u] |
860 |
853 |
861 fun choose_reps_in_nut (scope as {card_assigns, bits, datatypes, ofs, ...}) |
854 fun choose_reps_in_nut (scope as {card_assigns, bits, datatypes, ofs, ...}) |
1031 Op2 (Lambda, T, Any, y_u, |
1024 Op2 (Lambda, T, Any, y_u, |
1032 Op2 (Exist, bool_T, Any, x_u, |
1025 Op2 (Exist, bool_T, Any, x_u, |
1033 Op2 (And, bool_T, Any, |
1026 Op2 (And, bool_T, Any, |
1034 case u2 of |
1027 case u2 of |
1035 Op2 (Lambda, _, _, u21, u22) => |
1028 Op2 (Lambda, _, _, u21, u22) => |
1036 if num_occs_in_nut u21 u22 = 0 then |
1029 if num_occurrences_in_nut u21 u22 = 0 then |
1037 u22 |
1030 u22 |
1038 else |
1031 else |
1039 Op2 (Apply, bool_T, Any, u2, x_u) |
1032 Op2 (Apply, bool_T, Any, u2, x_u) |
1040 | _ => Op2 (Apply, bool_T, Any, u2, x_u), |
1033 | _ => Op2 (Apply, bool_T, Any, u2, x_u), |
1041 |
1034 |
1073 val u2' = aux table' false Neut u2 |
1066 val u2' = aux table' false Neut u2 |
1074 val R = |
1067 val R = |
1075 if is_opt_rep (rep_of u2') orelse |
1068 if is_opt_rep (rep_of u2') orelse |
1076 (range_type T = bool_T andalso |
1069 (range_type T = bool_T andalso |
1077 not (is_Cst False (unrepify_nut_in_nut table false Neut |
1070 not (is_Cst False (unrepify_nut_in_nut table false Neut |
1078 u1 u2 |
1071 u1 u2))) then |
1079 |> optimize_nut))) then |
|
1080 opt_rep ofs T R |
1072 opt_rep ofs T R |
1081 else |
1073 else |
1082 unopt_rep R |
1074 unopt_rep R |
1083 in s_op2 Lambda T R u1' u2' end |
1075 in s_op2 Lambda T R u1' u2' end |
1084 | _ => raise NUT ("Nitpick_Nut.aux.choose_reps_in_nut", [u])) |
1076 | _ => raise NUT ("Nitpick_Nut.choose_reps_in_nut.aux", [u])) |
1085 | Op2 (oper, T, _, u1, u2) => |
1077 | Op2 (oper, T, _, u1, u2) => |
1086 if oper = All orelse oper = Exist then |
1078 if oper = All orelse oper = Exist then |
1087 let |
1079 let |
1088 val table' = fold (choose_rep_for_bound_var scope) (untuple I u1) |
1080 val table' = fold (choose_rep_for_bound_var scope) (untuple I u1) |
1089 table |
1081 table |