signature NITPICK_NUT = sig type hol_context = Nitpick_HOL.hol_context type scope = Nitpick_Scope.scope type name_pool = Nitpick_Peephole.name_pool type rep = Nitpick_Rep.rep
datatype op1 = Not |
Finite |
Converse |
Closure |
SingletonSet |
IsUnknown |
SafeThe |
First |
Second |
Cast
datatype op2 = All |
Exist | Or | And |
Less |
DefEq |
Eq |
Triad |
Composition |
Apply |
Lambda
datatype op3 = Let | If
datatype nut =
Cst of cst * typ * rep |
Op1 of op1 * typ * rep * nut |
Op2 of op2 * typ * rep * nut * nut |
Op3 of op3 * typ * rep * nut * nut * nut |
Tuple of typ * rep * nut list |
Construct of nut list * typ * rep * nut list |
BoundName of int * typ * rep * string |
FreeName ofstring * typ * rep |
ConstName ofstring * typ * rep |
BoundRel of Kodkod.n_ary_index * typ * rep * string |
FreeRel of Kodkod.n_ary_index * typ * rep * string |
RelReg of int * typ * rep |
FormulaReg of int * typ * rep
structure NameTable : TABLE
exception NUT ofstring * nut list
val string_for_nut : Proof.context -> nut -> string val inline_nut : nut -> bool val type_of : nut -> typ val rep_of : nut -> rep val nickname_of : nut -> string val is_skolem_name : nut -> bool val is_eval_name : nut -> bool val is_Cst : cst -> nut -> bool val fold_nut : (nut -> 'a -> 'a) -> nut -> 'a -> 'a val map_nut : (nut -> nut) -> nut -> nut val untuple : (nut -> 'a) -> nut -> 'a list val add_free_and_const_names :
nut -> nut list * nut list -> nut list * nut list val name_ord : nut ord val the_name : 'a NameTable.table -> nut -> 'a val the_rel : nut NameTable.table -> nut -> Kodkod.n_ary_index val nut_from_term : hol_context -> op2 -> term -> nut val is_fully_representable_set : nut -> bool val choose_reps_for_free_vars :
scope -> (string * typ) list -> nut list -> rep NameTable.table
-> nut list * rep NameTable.table val choose_reps_for_consts :
scope -> bool -> nut list -> rep NameTable.table
-> nut list * rep NameTable.table val choose_reps_for_all_sels :
scope -> rep NameTable.table -> nut list * rep NameTable.table val choose_reps_in_nut :
scope -> bool -> rep NameTable.table -> bool -> nut -> nut val rename_free_vars :
nut list -> name_pool -> nut NameTable.table
-> nut list * name_pool * nut NameTable.table val rename_vars_in_nut : name_pool -> nut NameTable.table -> nut -> nut end;
structure Nitpick_Nut : NITPICK_NUT = struct
open Nitpick_Util open Nitpick_HOL open Nitpick_Scope open Nitpick_Peephole open Nitpick_Rep
datatype op1 = Not |
Finite |
Converse |
Closure |
SingletonSet |
IsUnknown |
SafeThe |
First |
Second |
Cast
datatype op2 = All |
Exist | Or | And |
Less |
DefEq |
Eq |
Triad |
Composition |
Apply |
Lambda
datatype op3 = Let | If
datatype nut =
Cst of cst * typ * rep |
Op1 of op1 * typ * rep * nut |
Op2 of op2 * typ * rep * nut * nut |
Op3 of op3 * typ * rep * nut * nut * nut |
Tuple of typ * rep * nut list |
Construct of nut list * typ * rep * nut list |
BoundName of int * typ * rep * string |
FreeName ofstring * typ * rep |
ConstName ofstring * typ * rep |
BoundRel of KK.n_ary_index * typ * rep * string |
FreeRel of KK.n_ary_index * typ * rep * string |
RelReg of int * typ * rep |
FormulaReg of int * typ * rep
fun fold_nut f u = case u of
Op1 (_, _, _, u1) => fold_nut f u1
| Op2 (_, _, _, u1, u2) => fold_nut f u1 #> fold_nut f u2
| Op3 (_, _, _, u1, u2, u3) => fold_nut f u1 #> fold_nut f u2 #> fold_nut f u3
| Tuple (_, _, us) => fold (fold_nut f) us
| Construct (us', _, _, us) => fold (fold_nut f) us #> fold (fold_nut f) us'
| _ => f u
fun map_nut f u = case u of
Op1 (oper, T, R, u1) => Op1 (oper, T, R, map_nut f u1)
| Op2 (oper, T, R, u1, u2) => Op2 (oper, T, R, map_nut f u1, map_nut f u2)
| Op3 (oper, T, R, u1, u2, u3) =>
Op3 (oper, T, R, map_nut f u1, map_nut f u2, map_nut f u3)
| Tuple (T, R, us) => Tuple (T, R, map (map_nut f) us)
| Construct (us', T, R, us) =>
Construct (map (map_nut f) us', T, R, map (map_nut f) us)
| _ => f u
fun num_occurrences_in_nut needle_u stack_u =
fold_nut (fn u => if u = needle_u then Integer.add 1else I) stack_u 0 val is_subnut_of = not_equal 0 oo num_occurrences_in_nut
fun substitute_in_nut needle_u needle_u' =
map_nut (fn u => if u = needle_u then needle_u' else u)
val add_free_and_const_names =
fold_nut (fn u => case u of
FreeName _ => apfst (insert (op =) u)
| ConstName _ => apsnd (insert (op =) u)
| _ => I)
fun modify_name_rep (BoundName (j, T, _, nick)) R = BoundName (j, T, R, nick)
| modify_name_rep (FreeName (s, T, _)) R = FreeName (s, T, R)
| modify_name_rep (ConstName (s, T, _)) R = ConstName (s, T, R)
| modify_name_rep u _ = raise NUT ("Nitpick_Nut.modify_name_rep", [u])
fun the_name table name = case NameTable.lookup table name of
SOME u => u
| NONE => raise NUT ("Nitpick_Nut.the_name", [name])
fun the_rel table name = case the_name table name of
FreeRel (x, _, _, _) => x
| u => raise NUT ("Nitpick_Nut.the_rel", [u])
fun mk_fst (_, Const (\<^const_name>\<open>Pair\<close>, T) $ t1 $ _) = (domain_type T, t1)
| mk_fst (T, t) = letval res_T = fst (HOLogic.dest_prodT T) in
(res_T, Const (\<^const_name>\<open>fst\<close>, T --> res_T) $ t) end
fun mk_snd (_, Const (\<^const_name>\<open>Pair\<close>, T) $ _ $ t2) =
(domain_type (range_type T), t2)
| mk_snd (T, t) = letval res_T = snd (HOLogic.dest_prodT T) in
(res_T, Const (\<^const_name>\<open>snd\<close>, T --> res_T) $ t) end
fun factorize (z as (Type (\<^type_name>\<open>prod\<close>, _), _)) =
maps factorize [mk_fst z, mk_snd z]
| factorize z = [z]
fun nut_from_term (hol_ctxt as {ctxt, ...}) eq = let fun aux eq ss Ts t = let valsub = aux Eq ss Ts valsub' = aux eq ss Ts fun sub_abs s T = aux eq (s :: ss) (T :: Ts) fun sub_equals T t1 t2 = let val (binder_Ts, body_T) = strip_type (domain_type T) val n = length binder_Ts in if eq = Eq andalso n > 0then let val t1 = incr_boundvars n t1 val t2 = incr_boundvars n t2 val xs = map Bound (n - 1 downto 0) val equation = Const (\<^const_name>\<open>HOL.eq\<close>,
body_T --> body_T --> bool_T)
$ betapplys (t1, xs) $ betapplys (t2, xs) val t =
fold_rev (fn T => fn (t, j) =>
(Const (\<^const_name>\<open>All\<close>, T --> bool_T)
$ Abs ("x" ^ nat_subscript j, T, t), j - 1))
binder_Ts (equation, n) |> fst insub' t end else
Op2 (eq, bool_T, Any, aux Eq ss Ts t1, aux Eq ss Ts t2) end fun do_quantifier quant s T t1 = let val bound_u = BoundName (length Ts, T, Any, s) val body_u = sub_abs s T t1 in Op2 (quant, bool_T, Any, bound_u, body_u) end fun do_apply t0 ts = let val (ts', t2) = split_last ts val t1 = list_comb (t0, ts') val T1 = fastype_of1 (Ts, t1) in Op2 (Apply, pseudo_range_type T1, Any, sub t1, sub t2) end fun do_construct (x as (_, T)) ts = case num_binder_types T - length ts of 0 => Construct (map ((fn (s', T') => ConstName (s', T', Any))
o nth_sel_for_constr x)
(~1 upto num_sels_for_constr_type T - 1),
body_type T, Any,
ts |> map (`(curry fastype_of1 Ts))
|> maps factorize |> map (sub o snd))
| k => sub (eta_expand Ts t k) in case strip_comb t of
(Const (\<^const_name>\<open>Pure.all\<close>, _), [Abs (s, T, t1)]) =>
do_quantifier All s T t1
| (t0 as Const (\<^const_name>\<open>Pure.all\<close>, _), [t1]) => sub' (t0 $ eta_expand Ts t1 1)
| (Const (\<^const_name>\<open>Pure.eq\<close>, T), [t1, t2]) => sub_equals T t1 t2
| (Const (\<^const_name>\<open>Pure.imp\<close>, _), [t1, t2]) =>
Op2 (Or, prop_T, Any, Op1 (Not, prop_T, Any, sub t1), sub' t2)
| (Const (\<^const_name>\<open>Pure.conjunction\<close>, _), [t1, t2]) =>
Op2 (And, prop_T, Any, sub' t1, sub' t2)
| (Const (\<^const_name>\<open>Trueprop\<close>, _), [t1]) => sub' t1
| (Const (\<^const_name>\<open>Not\<close>, _), [t1]) =>
(casesub t1 of
Op1 (Not, _, _, u11) => u11
| u1 => Op1 (Not, bool_T, Any, u1))
| (Const (\<^const_name>\<open>False\<close>, T), []) => Cst (False, T, Any)
| (Const (\<^const_name>\<open>True\<close>, T), []) => Cst (True, T, Any)
| (Const (\<^const_name>\<open>All\<close>, _), [Abs (s, T, t1)]) =>
do_quantifier All s T t1
| (t0 as Const (\<^const_name>\<open>All\<close>, _), [t1]) => sub' (t0 $ eta_expand Ts t1 1)
| (Const (\<^const_name>\<open>Ex\<close>, _), [Abs (s, T, t1)]) =>
do_quantifier Exist s T t1
| (t0 as Const (\<^const_name>\<open>Ex\<close>, _), [t1]) => sub' (t0 $ eta_expand Ts t1 1)
| (Const (\<^const_name>\<open>HOL.eq\<close>, T), [t1]) =>
Op1 (SingletonSet, range_type T, Any, sub t1)
| (Const (\<^const_name>\<open>HOL.eq\<close>, T), [t1, t2]) => sub_equals T t1 t2
| (Const (\<^const_name>\<open>HOL.conj\<close>, _), [t1, t2]) =>
Op2 (And, bool_T, Any, sub' t1, sub' t2)
| (Const (\<^const_name>\<open>HOL.disj\<close>, _), [t1, t2]) =>
Op2 (Or, bool_T, Any, sub t1, sub t2)
| (Const (\<^const_name>\<open>HOL.implies\<close>, _), [t1, t2]) =>
Op2 (Or, bool_T, Any, Op1 (Not, bool_T, Any, sub t1), sub' t2)
| (Const (\<^const_name>\<open>If\<close>, T), [t1, t2, t3]) =>
Op3 (If, nth_range_type 3 T, Any, sub t1, sub t2, sub t3)
| (Const (\<^const_name>\<open>Let\<close>, T), [t1, Abs (s, T', t2)]) =>
Op3 (Let, nth_range_type 2 T, Any, BoundName (length Ts, T', Any, s), sub t1, sub_abs s T' t2)
| (t0 as Const (\<^const_name>\<open>Let\<close>, _), [t1, t2]) => sub (t0 $ t1 $ eta_expand Ts t2 1)
| (Const (\<^const_name>\<open>Pair\<close>, T), [t1, t2]) =>
Tuple (nth_range_type 2 T, Any, mapsub [t1, t2])
| (Const (\<^const_name>\<open>fst\<close>, T), [t1]) =>
Op1 (First, range_type T, Any, sub t1)
| (Const (\<^const_name>\<open>snd\<close>, T), [t1]) =>
Op1 (Second, range_type T, Any, sub t1)
| (Const (\<^const_name>\<open>Set.member\<close>, _), [t1, t2]) => do_apply t2 [t1]
| (Const (\<^const_name>\<open>Collect\<close>, _), [t1]) => sub t1
| (Const (\<^const_name>\<open>Id\<close>, T), []) => Cst (Iden, T, Any)
| (Const (\<^const_name>\<open>converse\<close>, T), [t1]) =>
Op1 (Converse, range_type T, Any, sub t1)
| (Const (\<^const_name>\<open>trancl\<close>, T), [t1]) =>
Op1 (Closure, range_type T, Any, sub t1)
| (Const (\<^const_name>\<open>relcomp\<close>, T), [t1, t2]) =>
Op2 (Composition, nth_range_type 2 T, Any, sub t1, sub t2)
| (Const (x as (s as \<^const_name>\<open>Suc\<close>, T)), []) => if is_built_in_const x then Cst (Suc, T, Any) elseif is_constr ctxt x then do_construct x [] else ConstName (s, T, Any)
| (Const (\<^const_name>\<open>finite\<close>, T), [t1]) =>
(if is_finite_type hol_ctxt (domain_type T) then
Cst (True, bool_T, Any) elsecase t1 of Const (\<^const_name>\<open>top\<close>, _) => Cst (False, bool_T, Any)
| _ => Op1 (Finite, bool_T, Any, sub t1))
| (Const (\<^const_name>\<open>nat\<close>, T), []) => Cst (IntToNat, T, Any)
| (Const (x as (s as \<^const_name>\<open>zero_class.zero\<close>, T)), []) => if is_built_in_const x then Cst (Num 0, T, Any) elseif is_constr ctxt x then do_construct x [] else ConstName (s, T, Any)
| (Const (x as (s as \<^const_name>\<open>one_class.one\<close>, T)), []) => if is_built_in_const x then Cst (Num 1, T, Any) else ConstName (s, T, Any)
| (Const (x as (s as \<^const_name>\<open>plus_class.plus\<close>, T)), []) => if is_built_in_const x then Cst (Add, T, Any) else ConstName (s, T, Any)
| (Const (x as (s as \<^const_name>\<open>minus_class.minus\<close>, T)), []) => if is_built_in_const x then Cst (Subtract, T, Any) else ConstName (s, T, Any)
| (Const (x as (s as \<^const_name>\<open>times_class.times\<close>, T)), []) => if is_built_in_const x then Cst (Multiply, T, Any) else ConstName (s, T, Any)
| (Const (x as (s as \<^const_name>\<open>Rings.divide\<close>, T)), []) => if is_built_in_const x then Cst (Divide, T, Any) else ConstName (s, T, Any)
| (t0 as Const (x as (\<^const_name>\<open>ord_class.less\<close>, _)),
ts as [t1, t2]) => if is_built_in_const x then
Op2 (Less, bool_T, Any, sub t1, sub t2) else
do_apply t0 ts
| (t0 as Const (x as (\<^const_name>\<open>ord_class.less_eq\<close>, T)),
ts as [t1, t2]) => if is_built_in_const x then (* FIXME: find out if this case is necessary *)
Op1 (Not, bool_T, Any, Op2 (Less, bool_T, Any, sub t2, sub t1)) else
do_apply t0 ts
| (Const (\<^const_name>\<open>nat_gcd\<close>, T), []) => Cst (Gcd, T, Any)
| (Const (\<^const_name>\<open>nat_lcm\<close>, T), []) => Cst (Lcm, T, Any)
| (Const (x as (s as \<^const_name>\<open>uminus_class.uminus\<close>, T)), []) => if is_built_in_const x then letval num_T = domain_type T in
Op2 (Apply, num_T --> num_T, Any,
Cst (Subtract, num_T --> num_T --> num_T, Any),
Cst (Num 0, num_T, Any)) end else
ConstName (s, T, Any)
| (Const (\<^const_name>\<open>unknown\<close>, T), []) => Cst (Unknown, T, Any)
| (Const (\<^const_name>\<open>is_unknown\<close>, _), [t1]) =>
Op1 (IsUnknown, bool_T, Any, sub t1)
| (Const (\<^const_name>\<open>safe_The\<close>, Type (\<^type_name>\<open>fun\<close>, [_, T2])), [t1]) =>
Op1 (SafeThe, T2, Any, sub t1)
| (Const (\<^const_name>\<open>Frac\<close>, T), []) => Cst (Fracs, T, Any)
| (Const (\<^const_name>\<open>norm_frac\<close>, T), []) =>
Cst (NormFrac, T, Any)
| (Const (\<^const_name>\<open>of_nat\<close>, T as \<^typ>\<open>nat => int\<close>), []) =>
Cst (NatToInt, T, Any)
| (Const (\<^const_name>\<open>of_nat\<close>,
T as \<^typ>\<open>unsigned_bit word => signed_bit word\<close>), []) =>
Cst (NatToInt, T, Any)
| (t0 as Const (x as (s, T)), ts) => if is_constr ctxt x then
do_construct x ts elseifString.isPrefix numeral_prefix s then
Cst (Num (the (Int.fromString (unprefix numeral_prefix s))), T, Any) else
(case arity_of_built_in_const x of
SOME n =>
(case n - length ts of 0 => raise TERM ("Nitpick_Nut.nut_from_term.aux", [t])
| k => if k > 0thensub (eta_expand Ts t k) else do_apply t0 ts)
| NONE => if null ts then ConstName (s, T, Any) else do_apply t0 ts)
| (Free (s, T), []) => FreeName (s, T, Any)
| (Var _, []) => raise TERM ("Nitpick_Nut.nut_from_term.aux", [t])
| (Bound j, []) =>
BoundName (length Ts - j - 1, nth Ts j, Any, nth ss j)
| (Abs (s, T, t1), []) =>
Op2 (Lambda, T --> fastype_of1 (T :: Ts, t1), Any,
BoundName (length Ts, T, Any, s), sub_abs s T t1)
| (t0, ts) => do_apply t0 ts end in aux eq [] [] end
fun is_fully_representable_set u = not (is_opt_rep (rep_of u)) andalso case u of
FreeName _ => true
| Op1 (SingletonSet, _, _, _) => true
| Op1 (Converse, _, _, u1) => is_fully_representable_set u1
| Op2 (Lambda, _, _, _, Cst (False, _, _)) => true
| Op2 (oper, _, _, u1, _) => if oper = Apply then case u1 of
ConstName (s, _, _) =>
is_sel_like_and_no_discr s orelse s = \<^const_name>\<open>set\<close>
| _ => false else false
| _ => false
fun rep_for_abs_fun scope T = letval (R1, R2) = best_non_opt_symmetric_reps_for_fun_type scope T in
Func (R1, (card_of_rep R1 <> card_of_rep R2 ? Opt) R2) end
fun choose_rep_for_free_var scope pseudo_frees v (vs, table) = let val R = (ifexists (curry (op =) (nickname_of v) o fst) pseudo_frees then
best_opt_set_rep_for_type else
best_non_opt_set_rep_for_type) scope (type_of v) val v = modify_name_rep v R in (v :: vs, NameTable.update (v, R) table) end
fun choose_rep_for_const (scope as {hol_ctxt = {ctxt, ...}, ...}) total_consts v
(vs, table) = let val x as (s, T) = (nickname_of v, type_of v) val R = (if is_abs_fun ctxt x then
rep_for_abs_fun elseif is_rep_fun ctxt x then
Func oo best_non_opt_symmetric_reps_for_fun_type elseif total_consts orelse is_skolem_name v orelse
member (op =) [\<^const_name>\<open>bisim\<close>,
\<^const_name>\<open>bisim_iterator_max\<close>]
(original_name s) then
best_non_opt_set_rep_for_type elseif member (op =) [\<^const_name>\<open>set\<close>, \<^const_name>\<open>distinct\<close>,
\<^const_name>\<open>ord_class.less\<close>,
\<^const_name>\<open>ord_class.less_eq\<close>]
(original_name s) then
best_set_rep_for_type else
best_opt_set_rep_for_type) scope T val v = modify_name_rep v R in (v :: vs, NameTable.update (v, R) table) end
fun choose_reps_for_free_vars scope pseudo_frees vs table =
fold (choose_rep_for_free_var scope pseudo_frees) vs ([], table)
fun choose_reps_for_consts scope total_consts vs table =
fold (choose_rep_for_const scope total_consts) vs ([], table)
fun choose_rep_for_nth_sel_for_constr (scope as {hol_ctxt, binarize, ...})
(x as (_, T)) n (vs, table) = let val (s', T') = binarized_and_boxed_nth_sel_for_constr hol_ctxt binarize x n val R' = if n = ~1 orelse is_word_type (body_type T) orelse
(is_fun_type (range_type T') andalso
is_boolean_type (body_type T')) orelse
(is_set_type (body_type T')) then
best_non_opt_set_rep_for_type scope T' else
best_opt_set_rep_for_type scope T' |> unopt_rep val v = ConstName (s', T', R') in (v :: vs, NameTable.update (v, R') table) end
fun choose_rep_for_sels_for_constr scope (x as (_, T)) =
fold_rev (choose_rep_for_nth_sel_for_constr scope x)
(~1 upto num_sels_for_constr_type T - 1)
fun choose_rep_for_sels_of_data_type _ ({deep = false, ...} : data_type_spec) = I
| choose_rep_for_sels_of_data_type scope {constrs, ...} =
fold_rev (choose_rep_for_sels_for_constr scope o #const) constrs
fun choose_reps_for_all_sels (scope as {data_types, ...}) =
fold (choose_rep_for_sels_of_data_type scope) data_types o pair []
val min_univ_card = 2
fun choose_rep_for_bound_var scope v = let val R = best_one_rep_for_type scope (type_of v) val arity = arity_of_rep R in if arity > KK.max_arity min_univ_card then raise TOO_LARGE ("Nitpick_Nut.choose_rep_for_bound_var", "arity " ^ string_of_int arity ^ " of bound variable \
\too large") else
NameTable.update (v, R) end
(* A nut is said to be constructive if whenever it evaluates to unknown in our three-valuedlogic,itwouldevaluatetoanunrepresentablevalue("Unrep") accordingtotheHOLsemantics.Forexample,"Sucn"isconstructiveif"n"
is representable or "Unrep", because unknown implies "Unrep". *) fun is_constructive u =
is_Cst Unrep u orelse
(not (is_fun_or_set_type (type_of u)) andalso not (is_opt_rep (rep_of u))) orelse case u of
Cst (Num _, _, _) => true
| Cst (cst, T, _) => body_type T = nat_T andalso (cst = Suc orelse cst = Add)
| Op2 (Apply, _, _, u1, u2) => forall is_constructive [u1, u2]
| Op3 (If, _, _, u1, u2, u3) => not (is_opt_rep (rep_of u1)) andalso forall is_constructive [u2, u3]
| Tuple (_, _, us) => forall is_constructive us
| Construct (_, _, _, us) => forall is_constructive us
| _ => false
fun unknown_boolean T R =
Cst (case R of Formula Pos => False | Formula Neg => True | _ => Unknown,
T, R)
fun s_op1 oper T R u1 =
((if oper = Notthen if is_Cst True u1 then Cst (False, T, R) elseif is_Cst False u1 then Cst (True, T, R) elseraise SAME () else raise SAME ()) handle SAME () => Op1 (oper, T, R, u1))
fun s_op2 oper T R u1 u2 =
((case oper of All => if is_subnut_of u1 u2 then Op2 (All, T, R, u1, u2) else u2
| Exist => if is_subnut_of u1 u2 then Op2 (Exist, T, R, u1, u2) else u2
| Or => ifexists (is_Cst True) [u1, u2] then Cst (True, T, unopt_rep R) elseif is_Cst False u1 then u2 elseif is_Cst False u2 then u1 elseraise SAME ()
| And => ifexists (is_Cst False) [u1, u2] then Cst (False, T, unopt_rep R) elseif is_Cst True u1 then u2 elseif is_Cst True u2 then u1 elseraise SAME ()
| Eq =>
(case apply2 (is_Cst Unrep) (u1, u2) of
(true, true) => unknown_boolean T R
| (false, false) => raise SAME ()
| _ => if forall (is_opt_rep o rep_of) [u1, u2] thenraise SAME () else Cst (False, T, Formula Neut))
| Triad => if is_Cst True u1 then u1 elseif is_Cst False u2 then u2 elseraise SAME ()
| Apply => if is_Cst Unrep u1 then
Cst (Unrep, T, R) elseif is_Cst Unrep u2 then if is_boolean_type T then if is_fully_representable_set u1 then Cst (False, T, Formula Neut) else unknown_boolean T R elseif is_constructive u1 then
Cst (Unrep, T, R) elsecase u1 of
Op2 (Apply, _, _, ConstName (\<^const_name>\<open>List.append\<close>, _, _), _) =>
Cst (Unrep, T, R)
| _ => raise SAME () else raise SAME ()
| _ => raise SAME ()) handle SAME () => Op2 (oper, T, R, u1, u2))
fun s_op3 oper T R u1 u2 u3 =
((case oper of Let => if inline_nut u2 orelse num_occurrences_in_nut u1 u3 < 2then
substitute_in_nut u1 u2 u3 else raise SAME ()
| _ => raise SAME ()) handle SAME () => Op3 (oper, T, R, u1, u2, u3))
fun s_tuple T R us = ifexists (is_Cst Unrep) us then Cst (Unrep, T, R) else Tuple (T, R, us)
fun untuple f (Tuple (_, _, us)) = maps (untuple f) us
| untuple f u = [f u]
fun choose_reps_in_nut (scope as {card_assigns, bits, data_types, ofs, ...})
unsound table def = let val bool_atom_R = Atom (2, offset_of_type ofs bool_T) fun bool_rep polar opt = if polar = Neut andalso opt then Opt bool_atom_R else Formula polar fun triad u1 u2 = s_op2 Triad (type_of u1) (Opt bool_atom_R) u1 u2 fun triad_fn f = triad (f Pos) (f Neg) fun unrepify_nut_in_nut table def polar needle_u = letval needle_T = type_of needle_u in
substitute_in_nut needle_u
(Cst (if is_fun_or_set_type needle_T then Unknown else Unrep, needle_T, Any))
#> aux table def polar end and aux table def polar u = let val gsub = aux table valsub = gsub false Neut in case u of
Cst (False, T, _) => Cst (False, T, Formula Neut)
| Cst (True, T, _) => Cst (True, T, Formula Neut)
| Cst (Num j, T, _) => if is_word_type T then
Cst (if is_twos_complement_representable bits j then Num j else Unrep, T, best_opt_set_rep_for_type scope T) else let val (k, j0) = spec_of_type scope T val ok = (if T = int_T then atom_for_int (k, j0) j <> ~1 else j < k) in if ok then Cst (Num j, T, Atom (k, j0)) else Cst (Unrep, T, Opt (Atom (k, j0))) end
| Cst (Suc, T as Type (\<^type_name>\<open>fun\<close>, [T1, _]), _) => letval R = Atom (spec_of_type scope T1) in
Cst (Suc, T, Func (R, Opt R)) end
| Cst (Fracs, T, _) =>
Cst (Fracs, T, best_non_opt_set_rep_for_type scope T)
| Cst (NormFrac, T, _) => letval R1 = Atom (spec_of_type scope (domain_type T)) in
Cst (NormFrac, T, Func (R1, Func (R1, Opt (Struct [R1, R1])))) end
| Cst (cst, T, _) => if cst = Unknown orelse cst = Unrep then case (is_boolean_type T, polar |> unsound ? flip_polarity) of
(true, Pos) => Cst (False, T, Formula Pos)
| (true, Neg) => Cst (True, T, Formula Neg)
| _ => Cst (cst, T, best_opt_set_rep_for_type scope T) elseif member (op =) [Add, Subtract, Multiply, Divide, Gcd, Lcm]
cst then let val T1 = domain_type T val R1 = Atom (spec_of_type scope T1) val total = T1 = nat_T andalso
(cst = Subtract orelse cst = Divide orelse cst = Gcd) in Cst (cst, T, Func (R1, Func (R1, (not total ? Opt) R1))) end elseif cst = NatToInt orelse cst = IntToNat then let val (dom_card, dom_j0) = spec_of_type scope (domain_type T) val (ran_card, ran_j0) = spec_of_type scope (range_type T) val total = not (is_word_type (domain_type T)) andalso
(if cst = NatToInt then
max_int_for_card ran_card >= dom_card + 1 else
max_int_for_card dom_card < ran_card) in
Cst (cst, T, Func (Atom (dom_card, dom_j0),
Atom (ran_card, ran_j0) |> not total ? Opt)) end else
Cst (cst, T, best_set_rep_for_type scope T)
| Op1 (Not, T, _, u1) =>
(case gsub def (flip_polarity polar) u1 of
Op2 (Triad, T, _, u11, u12) =>
triad (s_op1 Not T (Formula Pos) u12)
(s_op1 Not T (Formula Neg) u11)
| u1' => s_op1 Not T (flip_rep_polarity (rep_of u1')) u1')
| Op1 (IsUnknown, T, _, u1) => letval u1 = sub u1 in if is_opt_rep (rep_of u1) then Op1 (IsUnknown, T, Formula Neut, u1) else Cst (False, T, Formula Neut) end
| Op1 (oper, T, _, u1) => let val u1 = sub u1 val R1 = rep_of u1 val R = case oper of
Finite => bool_rep polar (is_opt_rep R1)
| _ => (if is_opt_rep R1 then best_opt_set_rep_for_type else best_non_opt_set_rep_for_type) scope T in s_op1 oper T R u1 end
| Op2 (Less, T, _, u1, u2) => let val u1 = sub u1 val u2 = sub u2 val R = bool_rep polar (exists (is_opt_rep o rep_of) [u1, u2]) in s_op2 Less T R u1 u2 end
| Op2 (DefEq, T, _, u1, u2) =>
s_op2 DefEq T (Formula Neut) (sub u1) (sub u2)
| Op2 (Eq, T, _, u1, u2) => let val u1' = sub u1 val u2' = sub u2 fun non_opt_case () = s_op2 Eq T (Formula polar) u1' u2' fun opt_opt_case () = if polar = Neut then
triad_fn (fn polar => s_op2 Eq T (Formula polar) u1' u2') else
non_opt_case () fun hybrid_case u = (* hackish optimization *) if is_constructive u then s_op2 Eq T (Formula Neut) u1' u2' else opt_opt_case () in if unsound orelse polar = Neg orelse
is_concrete_type data_types true (type_of u1) then case (is_opt_rep (rep_of u1'), is_opt_rep (rep_of u2')) of
(true, true) => opt_opt_case ()
| (true, false) => hybrid_case u1'
| (false, true) => hybrid_case u2'
| (false, false) => non_opt_case () else
Cst (False, T, Formula Pos)
|> polar = Neut ? (fn pos_u => triad pos_u (gsub def Neg u)) end
| Op2 (Apply, T, _, u1, u2) => let val u1 = sub u1 val u2 = sub u2 val T1 = type_of u1 val R1 = rep_of u1 val R2 = rep_of u2 val opt = case (u1, is_opt_rep R2) of
(ConstName (\<^const_name>\<open>set\<close>, _, _), false) => false
| _ => exists is_opt_rep [R1, R2] val ran_R = if is_boolean_type T then
bool_rep polar opt else
lazy_range_rep ofs T1 (fn () => card_of_type card_assigns T)
(unopt_rep R1)
|> opt ? opt_rep ofs T in s_op2 Apply T ran_R u1 u2 end
| Op2 (Lambda, T, _, u1, u2) =>
(case best_set_rep_for_type scope T of
R as Func (R1, _) => let val table' = NameTable.update (u1, R1) table val u1' = aux table'false Neut u1 val u2' = aux table'false Neut u2 val R = if is_opt_rep (rep_of u2') then opt_rep ofs T R else unopt_rep R in s_op2 Lambda T R u1' u2'end
| _ => raise NUT ("Nitpick_Nut.choose_reps_in_nut.aux", [u]))
| Op2 (oper, T, _, u1, u2) => if oper = All orelse oper = Exist then let val table' = fold (choose_rep_for_bound_var scope) (untuple I u1)
table val u1' = aux table' def polar u1 val u2' = aux table' def polar u2 in if polar = Neut andalso is_opt_rep (rep_of u2') then
triad_fn (fn polar => gsub def polar u) else letval quant_u = s_op2 oper T (Formula polar) u1' u2'in if def orelse
(unsound andalso (polar = Pos) = (oper = All)) orelse
is_complete_type data_types true (type_of u1) then
quant_u else let val connective = if oper = AllthenAndelseOr val unrepified_u = unrepify_nut_in_nut table def polar
u1 u2 in
s_op2 connective T
(min_rep (rep_of quant_u) (rep_of unrepified_u))
quant_u unrepified_u end end end elseif oper = Or orelse oper = Andthen let val u1' = gsub def polar u1 val u2' = gsub def polar u2 in
(if polar = Neut then case (is_opt_rep (rep_of u1'), is_opt_rep (rep_of u2')) of
(true, true) => triad_fn (fn polar => gsub def polar u)
| (true, false) =>
s_op2 oper T (Opt bool_atom_R)
(triad_fn (fn polar => gsub def polar u1)) u2'
| (false, true) =>
s_op2 oper T (Opt bool_atom_R)
u1' (triad_fn (fn polar => gsub def polar u2))
| (false, false) => raise SAME () else raise SAME ()) handle SAME () => s_op2 oper T (Formula polar) u1' u2' end else let val u1 = sub u1 val u2 = sub u2 val R =
best_non_opt_set_rep_for_type scope T
|> exists (is_opt_rep o rep_of) [u1, u2] ? opt_rep ofs T in s_op2 oper T R u1 u2 end
| Op3 (Let, T, _, u1, u2, u3) => let val u2 = sub u2 val R2 = rep_of u2 val table' = NameTable.update (u1, R2) table val u1 = modify_name_rep u1 R2 val u3 = aux table' false polar u3 in s_op3 Let T (rep_of u3) u1 u2 u3 end
| Op3 (If, T, _, u1, u2, u3) => let val u1 = sub u1 val u2 = gsub def polar u2 val u3 = gsub def polar u3 val min_R = min_rep (rep_of u2) (rep_of u3) val R = min_R |> is_opt_rep (rep_of u1) ? opt_rep ofs T in s_op3 If T R u1 u2 u3 end
| Tuple (T, _, us) => let val Rs = map (best_one_rep_for_type scope o type_of) us val us = mapsub us val R' = Struct Rs
|> exists (is_opt_rep o rep_of) us ? opt_rep ofs T in s_tuple T R' us end
| Construct (us', T, _, us) => let val us = mapsub us val Rs = map rep_of us val R = best_one_rep_for_type scope T val {total, ...} =
constr_spec data_types (original_name (nickname_of (hd us')), T) val opt = exists is_opt_rep Rs orelse not total in Construct (mapsub us', T, R |> opt ? Opt, us) end
| _ => letval u = modify_name_rep u (the_name table u) in if polar = Neut orelse not (is_boolean_type (type_of u)) orelse not (is_opt_rep (rep_of u)) then
u else
s_op1 Cast (type_of u) (Formula polar) u end end in aux table def Pos end
fun fresh_n_ary_index n [] ys = (0, (n, 1) :: ys)
| fresh_n_ary_index n ((m, j) :: xs) ys = if m = n then (j, ys @ ((m, j + 1) :: xs)) else fresh_n_ary_index n xs ((m, j) :: ys)
fun fresh_rel n {rels, vars, formula_reg, rel_reg} = letval (j, rels') = fresh_n_ary_index n rels [] in
(j, {rels = rels', vars = vars, formula_reg = formula_reg,
rel_reg = rel_reg}) end
fun fresh_var n {rels, vars, formula_reg, rel_reg} = letval (j, vars') = fresh_n_ary_index n vars [] in
(j, {rels = rels, vars = vars', formula_reg = formula_reg,
rel_reg = rel_reg}) end
fun rename_plain_var v (ws, pool, table) = let val is_formula = (rep_of v = Formula Neut) val fresh = if is_formula then fresh_formula_reg else fresh_rel_reg val (j, pool) = fresh pool val constr = if is_formula then FormulaReg else RelReg val w = constr (j, type_of v, rep_of v) in (w :: ws, pool, NameTable.update (v, w) table) end
fun shape_tuple (T as Type (\<^type_name>\<open>prod\<close>, [T1, T2])) (R as Struct [R1, R2])
us = letval arity1 = arity_of_rep R1 in
Tuple (T, R, [shape_tuple T1 R1 (List.take (us, arity1)),
shape_tuple T2 R2 (List.drop (us, arity1))]) end
| shape_tuple T (R as Vect (k, R')) us =
Tuple (T, R, map (shape_tuple (pseudo_range_type T) R')
(chunk_list (length us div k) us))
| shape_tuple T _ [u] = if type_of u = T then u elseraise NUT ("Nitpick_Nut.shape_tuple", [u])
| shape_tuple _ _ us = raise NUT ("Nitpick_Nut.shape_tuple", us)
fun rename_n_ary_var rename_free v (ws, pool, table) = let val T = type_of v val R = rep_of v val arity = arity_of_rep R val nick = nickname_of v val (constr, fresh) = if rename_free then (FreeRel, fresh_rel) else (BoundRel, fresh_var) in ifnot rename_free andalso arity > 1then let val atom_schema = atom_schema_of_rep R val type_schema = type_schema_of_rep T R val (js, pool) = funpow arity (fn (js, pool) => letval (j, pool) = fresh 1 pool in
(j :: js, pool) end)
([], pool) val ws' = @{map 3} (fn j => fn x => fn T =>
constr ((1, j), T, Atom x,
nick ^ " [" ^ string_of_int j ^ "]"))
(rev js) atom_schema type_schema in (ws' @ ws, pool, NameTable.update (v, shape_tuple T R ws') table) end else let val (j, pool) = case v of
ConstName _ => if is_sel_like_and_no_discr nick then case domain_type T of
\<^typ>\<open>unsigned_bit word\<close> =>
(snd unsigned_bit_word_sel_rel, pool)
| \<^typ>\<open>signed_bit word\<close> => (snd signed_bit_word_sel_rel, pool)
| _ => fresh arity pool else
fresh arity pool
| _ => fresh arity pool val w = constr ((arity, j), T, R, nick) in (w :: ws, pool, NameTable.update (v, w) table) end end
fun rename_free_vars vs pool table = let val (vs, pool, table) = fold (rename_n_ary_var true) vs ([], pool, table) in (rev vs, pool, table) end
fun rename_vars_in_nut pool table u = case u of
Cst _ => u
| Op1 (oper, T, R, u1) => Op1 (oper, T, R, rename_vars_in_nut pool table u1)
| Op2 (oper, T, R, u1, u2) => if oper = All orelse oper = Exist orelse oper = Lambda then let val (_, pool, table) = fold (rename_n_ary_var false) (untuple I u1)
([], pool, table) in
Op2 (oper, T, R, rename_vars_in_nut pool table u1,
rename_vars_in_nut pool table u2) end else
Op2 (oper, T, R, rename_vars_in_nut pool table u1,
rename_vars_in_nut pool table u2)
| Op3 (Let, T, R, u1, u2, u3) => if inline_nut u2 then let val u2 = rename_vars_in_nut pool table u2 val table = NameTable.update (u1, u2) table in rename_vars_in_nut pool table u3 end else let val bs = untuple I u1 val (_, pool, table') = fold rename_plain_var bs ([], pool, table) in
Op3 (Let, T, R, rename_vars_in_nut pool table' u1,
rename_vars_in_nut pool table u2,
rename_vars_in_nut pool table' u3) end
| Op3 (oper, T, R, u1, u2, u3) =>
Op3 (oper, T, R, rename_vars_in_nut pool table u1,
rename_vars_in_nut pool table u2, rename_vars_in_nut pool table u3)
| Tuple (T, R, us) => Tuple (T, R, map (rename_vars_in_nut pool table) us)
| Construct (us', T, R, us) =>
Construct (map (rename_vars_in_nut pool table) us', T, R, map (rename_vars_in_nut pool table) us)
| _ => the_name table u
end;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.