(* Data structure for rewrite table. *) type rewrite_table = { (* terms[t] is the list of ids at which t is present. *)
terms: (box_id list * cterm) Termtab.table, (* equiv[a] is list of (id, th), where th is "a == a'" under id. *)
equiv: ((box_id * thm) list) Termtab.table, (* Index of reachability under equiv. *)
all_equiv: ((box_id * thm) list) Termtab.table, (* contain[A] is the list of terms for which A is a direct subterm. *)
contain: (cterm list) Termtab.table, (* Rewrite info of a term. *)
simp: ((box_id * thm) list) Termtab.table, (* Subterm rewrite info of a term. *)
subsimp: ((box_id * thm) list) Termtab.table, (* Reverse of subsimp. Head rep of a term. *)
reps: ((box_id * thm) list) Termtab.table
}
signature REWRITE_TABLE = sig (* Construction and modification. *) val clean_resolved: box_id -> Proof.context -> Proof.context val clear_incr: Proof.context -> Proof.context
(* contain table. *) val add_contain: cterm -> term -> Proof.context -> Proof.context val immediate_contains: Proof.context -> term -> cterm list
(* terms table. *) val in_table_raw_ids: Proof.context -> term -> box_id list val in_table_raw_for_id: Proof.context -> box_id * term -> bool val in_table_raw: Proof.context -> term -> bool val add_term_raw: box_id * cterm -> Proof.context -> Proof.context val get_all_terms: Proof.context -> cterm list val get_all_id_terms: Proof.context -> (box_id * cterm) list
(* equiv table. *) val add_equiv: box_id * thm -> Proof.context -> Proof.context val equiv_neighs: Proof.context -> term -> (box_id * thm) list val get_all_equiv: Proof.context -> term -> (box_id * thm) list
(* simp table. *) val update_simp: box_id * thm -> Proof.context -> Proof.context val get_rewrite_info: Proof.context -> cterm -> (box_id * thm) list val get_rewrite: box_id -> Proof.context -> cterm -> thm
(* subsimp and rep tables. *) val get_subterm_rewrite_info: Proof.context -> cterm -> (box_id * thm) list val remove_rep: box_id * thm -> Proof.context -> Proof.context val update_subsimp: box_id * thm -> Proof.context -> Proof.context val get_head_rep_info: Proof.context -> term -> (box_id * thm) list val get_head_rep: box_id -> Proof.context -> term -> thm option val get_head_rep_with_id_th:
Proof.context -> box_id * thm -> (box_id * thm) list val get_cached_subterm_rewrite_info:
Proof.context -> term -> (box_id * thm) list val get_cached_subterm_rewrite: box_id -> Proof.context -> cterm -> thm
(* Simplification of arbitrary terms. *) val head_simplify: box_id -> Proof.context -> cterm -> thm val simplify: box_id -> Proof.context -> cterm -> thm val subterm_simplify: box_id -> Proof.context -> cterm -> thm val simp_val: box_id -> Proof.context -> cterm -> cterm val simp_val_t: box_id -> Proof.context -> term -> term val simplify_info: Proof.context -> cterm -> (box_id * thm) list val subterm_simplify_info: Proof.context -> cterm -> (box_id * thm) list val is_equiv: box_id -> Proof.context -> cterm * cterm -> bool val is_equiv_t: box_id -> Proof.context -> term * term -> bool
(* Computation of head equiv. *) val get_head_equiv: Proof.context -> cterm -> (box_id * thm) list val get_head_equiv_with_t:
Proof.context -> box_id * cterm -> term -> (box_id * thm) list
(* Update of whole rewrite table. *) val process_update_simp: (box_id * thm) list -> Proof.context -> Proof.context val equiv_info:
Proof.context -> box_id -> cterm * cterm -> (box_id * thm) list val equiv_info_t:
Proof.context -> box_id -> term * term -> (box_id * thm) list val subequiv_info:
Proof.context -> box_id -> cterm * cterm -> (box_id * thm) list val add_rewrite_raw: box_id -> thm -> Proof.context -> Proof.context val get_reachable_terms: bool -> Proof.context -> term list -> term list val complete_table: Proof.context -> (box_id * thm) list * Proof.context val add_term:
box_id * cterm -> Proof.context -> (box_id * thm) list * Proof.context val add_term_list:
(box_id * cterm) list -> Proof.context -> (box_id * thm) list * Proof.context val add_rewrite:
box_id * thm -> Proof.context -> (box_id * thm) list * Proof.context
(* Updating rewrite table from list of (id, th) pairs. *) val get_new_terms: Proof.context * Proof.context -> (box_id * cterm) list end;
(* equiv_eq_better ctxt info1 info2 means info2 is extraneous in the equivtable.
*) fun equiv_eq_better ctxt (id, th) (id', th') =
Util.rhs_of th aconv Util.rhs_of th' andalso BoxID.is_eq_ancestor ctxt id id'
(* simp_eq_better ctxt info1 info2 means info2 is extraneous in the simptable.
*) fun simp_eq_better ctxt (id, th) (id', th') = if BoxID.is_eq_ancestor ctxt id id' then letval (t, t') = (Util.rhs_of th, Util.rhs_of th') in t aconv t' orelse Term_Ord.term_ord (t, t') = LESS end elsefalse
fun clear_incr ctxt = let val {terms, equiv, all_equiv, contain, simp, subsimp, reps} =
Data.get ctxt
fun clear_one cmp infos = ifexists (BoxID.has_incr_id o fst) infos then
infos |> map (apfst BoxID.replace_incr_id)
|> Util.max_partial cmp else
infos
(* Add the information that t contains subt directly. *) fun add_contain ct subt ctxt = let val {contain, ...} = Data.get ctxt val contain_subt = the_default [] (Termtab.lookup contain subt) in if member (op aconvc) contain_subt ct then ctxt else ctxt |> Data.map (map_contain (Termtab.update (subt, ct :: contain_subt))) end
(* Get all terms that directly contains t. *) fun immediate_contains ctxt t = let val {contain, ...} = Data.get ctxt in
the_default [] (Termtab.lookup contain t) end
(*** Basic manipulation of the terms table. ***)
(* Return ids in which t is directly in table. *) fun in_table_raw_ids ctxt t = let val {terms, ...} = Data.get ctxt in case Termtab.lookup terms t of
NONE => []
| SOME (ids, _) => ids end
(* Whether the term is present in table at the given id. *) fun in_table_raw_for_id ctxt (id, t) = exists (BoxID.is_eq_descendent ctxt id) (in_table_raw_ids ctxt t)
(* Whether the term is present at any id. *) fun in_table_raw ctxt t =
length (in_table_raw_ids ctxt t) > 0
(* Add t to table at the given id. *) fun add_term_raw (id, ct) ctxt = let val t = Thm.term_of ct val prev_ids = in_table_raw_ids ctxt t val ids_t = (id :: prev_ids)
|> Util.max_partial (BoxID.is_eq_ancestor ctxt) in
ctxt |> Data.map (map_terms (Termtab.update (t, (ids_t, ct)))) end
(* Return list of all terms (at any ids) present in table. *) fun get_all_terms ctxt = let val {terms, ...} = Data.get ctxt in map (fn (_, (_, ct)) => ct) (Termtab.dest terms) end
(* Return list of all terms with ids present in table. *) fun get_all_id_terms ctxt = let val {terms, ...} = Data.get ctxt in
maps (fn (_, (ids, ct)) => map (rpair ct) ids)
(Termtab.dest terms) end
(*** Basic manipulation of equiv table. ***)
fun has_equiv_eq_better ctxt infos info' = exists (fn info => equiv_eq_better ctxt info info') infos
(* Add one way equivalence edge. Maintain the non-comparable property ofthesetofequivalenceedgesbetweenanytwonodes.cur_infois ofform(id,t==t').
*) fun add_equiv_raw (cur_info as (_, th)) ctxt = let val {equiv, ...} = Data.get ctxt val t = Util.lhs_of th val equiv_t = the_default [] (Termtab.lookup equiv t) in ifexists (fn info => equiv_eq_better ctxt info cur_info) equiv_t then ctxt else ctxt |> Data.map (map_equiv (
Termtab.update (
t, equiv_t |> filter_out (equiv_eq_better ctxt cur_info)
|> cons cur_info))) end
(* Add the given equivalence edge. *) fun add_equiv (id, th) ctxt = let val _ = assert (not (Util.lhs_of th aconv Util.rhs_of th)) "add_equiv: t == t'" in
ctxt |> add_equiv_raw (id, th)
|> add_equiv_raw (id, meta_sym th) end
(* Get all edges coming from t in the equiv graph. *) fun equiv_neighs ctxt t = let val {equiv, ...} = Data.get ctxt in case Termtab.lookup equiv t of
NONE => []
| SOME infos => infos end
fun get_all_equiv ctxt t = let val {all_equiv, ...} = Data.get ctxt in
the (Termtab.lookup all_equiv t) handleOption.Option => raise Fail "all_equiv: not found" end
(*** Basic manipulation of simp table. ***)
(* Update rewrite of t under id to th: t == t'. Similar to add_equiv_raw.
*) fun update_simp (id, th) ctxt = let val {simp, ...} = Data.get ctxt val ct = Thm.lhs_of th val t = Thm.term_of ct val simp_t = the_default [([], Thm.reflexive ct)] (Termtab.lookup simp t) in ifexists (fn info => simp_eq_better ctxt info (id, th)) simp_t then ctxt else
ctxt |> Data.map (map_simp (
Termtab.update (
t, simp_t |> filter_out (simp_eq_better ctxt (id, th))
|> cons (id, th)))) end
(* Get the entire rewrite info of t as stored directly in table.Returnasalistof(id,th)pairs.
*) fun get_rewrite_info ctxt ct = let val {simp, ...} = Data.get ctxt in case Termtab.lookup simp (Thm.term_of ct) of
NONE => [([], Thm.reflexive ct)]
| SOME infos => infos end
(* Return the rewrite of t under a given id, as stored directly in table.Returnt==tifnotintable.
*) fun get_rewrite id ctxt ct = case get_rewrite_info ctxt ct of
[] => Thm.reflexive ct
| ths' => ths' |> filter (BoxID.is_eq_descendent ctxt id o fst)
|> map snd
|> Util.max (rev_order o simp_ord)
(*** Basic manipulation of subsimp and rep tables. ***)
(* Given list of lists of simplifying infos indexed by term and then id,returnsimplifyinginfosindexedfirstbyidandthenterm.
*) fun merge_simp_infos ctxt lsts = let val ids = map (map fst) lsts |> BoxID.get_all_merges ctxt fun get_for_id_lst id lst =
lst |> filter (BoxID.is_eq_descendent ctxt id o fst)
|> map snd |> Util.max (rev_order o simp_ord) fun get_for_id id = (id, map (get_for_id_lst id) lsts) in map get_for_id ids end
(* Get entire subterm rewrite info of t. Return as a list of (id, rewrite)pairs.
*) fun get_subterm_rewrite_info ctxt ct = let val (cf, subs) = Drule.strip_comb ct in if null subs then [([], Thm.reflexive ct)] else
(map (get_rewrite_info ctxt) subs)
|> merge_simp_infos ctxt
|> map (fn (id, equivs) => (id, Util.comb_equiv (cf, equivs)))
|> Util.max_partial (simp_eq_better ctxt) end
(* Given a head rep (id, th) (where th is reverse of a subterm rewrite),removethfromtherepstable.
*) fun remove_rep (id, th) ctxt = let val {reps, ...} = Data.get ctxt val t = Util.lhs_of th val reps_t = the_default [] (Termtab.lookup reps t) val _ = assert (member eq_info reps_t (id, th)) "remove_rep: not found" in
ctxt |> Data.map (map_reps (Termtab.map_entry t (remove eq_info (id, th)))) end
(* Update subterm rewrite of t under id to th: t == t'. Also update therepstable(reverseofsubsimptable).
*) fun update_subsimp (id, th) ctxt = let val {subsimp, ...} = Data.get ctxt val (t, t') = (Util.lhs_of th, Util.rhs_of th) val subsimp_t = the_default [] (Termtab.lookup subsimp t) in ifexists (fn info => simp_eq_better ctxt info (id, th)) subsimp_t then ctxt else let val th' = meta_sym th val (rem, keep) = filter_split (simp_eq_better ctxt (id, th)) subsimp_t in
ctxt |> Data.map (map_subsimp (Termtab.update (t, (id, th) :: keep)))
|> Data.map (map_reps (Termtab.map_default (t', []) (cons (id, th'))))
|> fold remove_rep (map (apsnd meta_sym) rem) end end
(* Returns the list of (id, th) pairs, where th is t == t', such that t'subtermrewritestotatboxid.
*) fun get_head_rep_info ctxt t = let val {reps, ...} = Data.get ctxt in case Termtab.lookup reps t of
NONE => []
| SOME infos => infos end
(* Assume t is subterm simplified under id. Return SOME (t == v) if v isatermintherewritetablethatissubtermrewritestot,under thegivenid.Ifthereisnosuchv,returnNONE.
*) fun get_head_rep id ctxt t =
get_first (fn (id', t') => if BoxID.is_eq_ancestor ctxt id' id then SOME t'else NONE)
(get_head_rep_info ctxt t)
(* Returns head representations of the right side of th under id, or undermorerestrictiveassumptions.Mergetheequivalencetheorems withth.Notguaranteedtobenon-redundant.
*) fun get_head_rep_with_id_th ctxt (id, th) =
get_head_rep_info ctxt (Util.rhs_of th) |> map (BoxID.merge_eq_infos ctxt (id, th))
(* Using the subsimp table for subterm simplification. *) fun get_cached_subterm_rewrite_info ctxt t = let val {subsimp, ...} = Data.get ctxt in case Termtab.lookup subsimp t of
NONE => []
| SOME infos => infos end
(* Obtain the subterm simplification of t under id, or a less restrictiveassumption.
*) fun get_cached_subterm_rewrite id ctxt ct = case get_cached_subterm_rewrite_info ctxt (Thm.term_of ct) of
[] => Thm.reflexive ct
| ths' => ths' |> filter (BoxID.is_eq_descendent ctxt id o fst)
|> map snd
|> Util.max (rev_order o simp_ord)
(*** Simplification of terms not indexed in table. ***)
(* Assume t is subterm simplified under id. *) fun head_simplify id ctxt ct = case get_head_rep id ctxt (Thm.term_of ct) of
NONE => Thm.reflexive ct
| SOME th => Util.transitive_list [th, get_rewrite id ctxt (Thm.rhs_of th)]
(* First simplify subterms, then simplify head. *) fun simplify id ctxt ct = if in_table_raw ctxt (Thm.term_of ct) then
get_rewrite id ctxt ct else let val th = subterm_simplify id ctxt ct in
Util.transitive_list [th, head_simplify id ctxt (Thm.rhs_of th)] end
(* Simplify subterms, but not head. *) and subterm_simplify id ctxt ct = if in_table_raw ctxt (Thm.term_of ct) then
get_cached_subterm_rewrite id ctxt ct else let val (cf, subs) = Drule.strip_comb ct val equivs = map (simplify id ctxt) subs in
Util.comb_equiv (cf, equivs) end
(* Convenient function for getting simplified value. *) fun simp_val id ctxt ct = Thm.rhs_of (simplify id ctxt ct)
fun simp_val_t id ctxt t =
Util.rhs_of (simplify id ctxt (Thm.cterm_of ctxt t))
(* Get all simplifications and subterm-simplifications. *) fun simplify_info ctxt ct = if in_table_raw ctxt (Thm.term_of ct) then
get_rewrite_info ctxt ct else let val subterm_info = subterm_simplify_info ctxt ct fun get_rewrite_with_id_th (id', th') =
(get_rewrite_info ctxt (Thm.rhs_of th'))
|> map (BoxID.merge_eq_infos ctxt (id', th')) val head_info =
subterm_info |> maps (get_head_rep_with_id_th ctxt)
|> Util.max_partial (BoxID.id_is_eq_ancestor ctxt)
|> maps get_rewrite_with_id_th in
subterm_info @ head_info |> Util.max_partial (simp_eq_better ctxt) end
(* Note similarity with get_subterm_rewrite_info. *) and subterm_simplify_info ctxt ct = if in_table_raw ctxt (Thm.term_of ct) then
get_cached_subterm_rewrite_info ctxt (Thm.term_of ct) else let val (cf, subs) = Drule.strip_comb ct in if null subs then [([], Thm.reflexive ct)] else
(map (simplify_info ctxt) subs)
|> merge_simp_infos ctxt
|> map (fn (id, equivs) => (id, Util.comb_equiv (cf, equivs)))
|> Util.max_partial (simp_eq_better ctxt) end
(* Exported equivalence function. *) fun is_equiv id ctxt (ct1, ct2) =
ct1 aconvc ct2 orelse simp_val id ctxt ct1 aconvc simp_val id ctxt ct2
fun is_equiv_t id ctxt (t1, t2) =
t1 aconv t2 orelse is_equiv id ctxt (Thm.cterm_of ctxt t1, Thm.cterm_of ctxt t2)
(* No assumption on u. Get list of (id', u') pairs where id <= id', u' isinthetableequivalenttouunderid',andtheheadofu'is thesameasthatfort.If(id1,u1)and(id2,u2)aresuchthat id2impliesid1andallargumentsofu1,u2areequivalentunder t2,then(id2,u2)isnotincludedintheresults.This functionismuchfasterwhenuisintable(usesget_all_equiv directly).
*) fun get_head_equiv ctxt cu = let val u = Thm.term_of cu val _ = assert (not (Term.is_open u)) "get_all_head_equivs: u is open"
fun get_all_equiv_under_id (id', th') =
(get_all_equiv ctxt (Util.rhs_of th'))
|> map (BoxID.merge_eq_infos ctxt (id', th')) in if in_table_raw ctxt u then (* Get all equivs from table. *)
get_all_equiv ctxt u else
cu |> subterm_simplify_info ctxt
|> maps (get_head_rep_with_id_th ctxt)
|> Util.max_partial rep_eq_better
|> maps get_all_equiv_under_id
|> cons ([], Thm.reflexive cu)
|> Util.max_partial (equiv_eq_better ctxt) end
(* Get list of head equivs for cu, whose head agrees (or matches) with t. *) fun get_head_equiv_with_t ctxt (id, cu) t = let fun is_valid (_, th) = if Term.is_Var t thentrue elseif Term.is_Var (Term.head_of t) thentrue else Term.aconv_untyped (Term.head_of (Util.rhs_of th), Term.head_of t) in
(get_head_equiv ctxt cu)
|> filter is_valid
|> BoxID.merge_box_with_info ctxt id end
(*** Adding rewrite rules and maintain invariants of the table. ***)
(* Work out all consequences of updating simps in the rewrite table.Thisincludesupdatingsimpofneighboringnodes,and updatingsimps/subsimpsofnodesforwhichthecurrentnodeisa subterm.initsisalistofsimpstobeadded,whereeachelement isoftheform(id,t==t')updatingsimpoft.Inthisfunction wemaintainalistofsimplifications(to_process)thathavebeen addedtothetable,butwhoseconsequences(onneighboringterms andcontainingterms)needtobeprocessed.
*) fun process_update_simp inits ctxt = let fun eq_update ((id, th), (id', th')) =
(id = id' andalso Thm.prop_of th aconv Thm.prop_of th')
(* Add the simp (id, th) for the left side of th to the table.If(id,th)isnotredundant,add(id,th)tothelist ofsimpswhoseconsequencesneedtobeprocessed.
*) fun process_simp (id, th) (to_process, ctxt) = if simp_ord (th, get_rewrite id ctxt (Thm.lhs_of th)) = LESS then
(insert eq_update (id, th) to_process, update_simp (id, th) ctxt) else
(to_process, ctxt)
(* Recompute subterm simplifications of t. Update the subsimp tableaswellasthesimptable(inthelattercasepossibly addingtotheto_processlist.
*) fun process_term ct (to_process, ctxt) = let val subsimps = get_subterm_rewrite_info ctxt ct val ctxt' = fold update_subsimp subsimps ctxt in
fold process_simp subsimps (to_process, ctxt') end
(* Pull the first item of to_process and work out its consequences.
*) fun update_step (to_process, ctxt) = case to_process of
[] => ([], ctxt)
| (id, th) :: rest => let val t = Util.lhs_of th (* th: t == simp_t, th': t = t', result: t' = simp_t. *) fun process_neigh (id', th') =
BoxID.merge_eq_infos ctxt (id', meta_sym th') (id, th) val new_simp = map process_neigh (equiv_neighs ctxt t) in
(rest, ctxt) |> fold process_simp new_simp
|> fold process_term (immediate_contains ctxt t)
|> update_step end in
([], ctxt) |> fold process_simp inits |> update_step |> snd end
(* Return list of ids that are descendents of id at which t1 and t2 areequiv.
*) fun equiv_info ctxt id (ct1, ct2) = let val simp1 = simplify_info ctxt ct1 val simp2 = simplify_info ctxt ct2 fun compare (id1, th1) (id2, th2) = if Util.rhs_of th1 aconv Util.rhs_of th2 then
[(BoxID.merge_boxes ctxt (id1, id2), Util.transitive_list [th1, meta_sym th2])] else [] in
(maps (fn s1 => maps (compare s1) simp2) simp1)
|> BoxID.merge_box_with_info ctxt id
|> Util.max_partial (BoxID.id_is_eq_ancestor ctxt) end
fun equiv_info_t ctxt id (t1, t2) =
equiv_info ctxt id (Thm.cterm_of ctxt t1, Thm.cterm_of ctxt t2)
(* Return list of ids that are descendents of id at which t1 and t2 aresubtermequiv.
*) fun subequiv_info ctxt id (ct1, ct2) = ifnot ((Term.head_of (Thm.term_of ct1))
aconv Term.head_of (Thm.term_of ct2)) then [] elselet val simp1 = subterm_simplify_info ctxt ct1 val simp2 = subterm_simplify_info ctxt ct2 fun compare (id1, th1) (id2, th2) = if Util.rhs_of th1 aconv Util.rhs_of th2 then
[(BoxID.merge_boxes ctxt (id1, id2),
Util.transitive_list [th1, meta_sym th2])] else [] in
(maps (fn s1 => maps (compare s1) simp2) simp1)
|> BoxID.merge_box_with_info ctxt id
|> Util.max_partial (BoxID.id_is_eq_ancestor ctxt) end
(* Get list of terms reachable from the terms ts. If trav_contains = false,onlytravelalongequivedges.Otherwisealsotravelfromt toanytermcontainingt.
*) fun get_reachable_terms trav_contains ctxt ts = let fun helper (new, all) = case new of
[] => ([], all)
| t :: rest => let val contains = if trav_contains then map Thm.term_of (immediate_contains ctxt t) else [] val neighs = (equiv_neighs ctxt t)
|> map (fn (_, th) => Util.rhs_of th) val new' = (contains @ neighs)
|> distinct (op aconv)
|> subtract (op aconv) all valall' = new' @ all in
helper (rest @ new', all') end in
snd (helper (ts, ts)) end
fun add_all_equiv_raw (cur_info as (_, th)) ctxt = let val {all_equiv, ...} = Data.get ctxt val t = Util.lhs_of th val equiv_t = the_default [] (Termtab.lookup all_equiv t) in ifexists (fn info => equiv_eq_better ctxt info cur_info) equiv_t then ctxt else ctxt |> Data.map (map_all_equiv (
Termtab.update (
t, equiv_t |> filter_out (equiv_eq_better ctxt cur_info)
|> cons cur_info))) end
fun update_all_equiv id th ctxt = let val (ct1, ct2) = (Thm.lhs_of th, Thm.rhs_of th) val t1_equiv = get_all_equiv ctxt (Thm.term_of ct1) val t2_equiv = get_all_equiv ctxt (Thm.term_of ct2)
(* eq1 is t1 == t1', eq2 is t2 == t2', add t1' == t2' and t2' == t1'toall_equiv.
*) fun process_pair ((id1, eq1), (id2, eq2)) ctxt = let val id' = BoxID.merge_boxes
ctxt (id, BoxID.merge_boxes ctxt (id1, id2)) val eq = Util.transitive_list [meta_sym eq1, th, eq2] in
ctxt |> add_all_equiv_raw (id', eq)
|> add_all_equiv_raw (id', meta_sym eq) end in
fold process_pair (Util.all_pairs (t1_equiv, t2_equiv)) ctxt end
(* Assume t1 and t2 are already in table. Add equiv edge th: t1 == t2 and workoutalltheconsequences.
*) fun add_rewrite_raw id th ctxt = let val (ct1, ct2) = (Thm.lhs_of th, Thm.rhs_of th)
(* New simplifications. *) val t1_rinfo = get_rewrite_info ctxt ct1 val t2_rinfo = get_rewrite_info ctxt ct2 val t1_news = t2_rinfo |> map (BoxID.merge_eq_infos ctxt (id, th)) val t2_news = t1_rinfo |> map (BoxID.merge_eq_infos ctxt (id, meta_sym th)) in
ctxt |> add_equiv (id, th)
|> process_update_simp (t1_news @ t2_news)
|> update_all_equiv id th end
(* Add equiv edges so the rewrite table is consistent. That is, any two nodes that havethesamesimpshouldbeconnectedintheequivgraph.Also returnthelistofequivedgesadded.
*) fun complete_table ctxt = let fun find_new_equiv ct = let val equivs = get_all_equiv ctxt (Thm.term_of ct) in
(get_subterm_rewrite_info ctxt ct)
|> maps (get_head_rep_with_id_th ctxt)
|> Util.max_partial (equiv_eq_better ctxt)
|> filter_out (has_equiv_eq_better ctxt equivs) end val new_equivs = (maps find_new_equiv (get_all_terms ctxt))
|> Util.max_partial (BoxID.id_is_eq_ancestor ctxt) in case new_equivs of
[] => ([], ctxt)
| (id, th) :: _ => (* Add bi-directional edges for terms with the same subterm simplification.Keeptrackoflistofedgesadded.
*) let val ctxt' = ctxt |> add_rewrite_raw id th val (edges, ctxt'') = complete_table ctxt' in
((id, th) :: edges, ctxt'') end end
(* Add term t to rewrite table at box id. The primed version (used in add_rewrite_thm)addtandallitssubtermstothetable.The unprimedversionalsoaddnewequivedgesifnecessary,resulting isaconsistentrewritetable.
*) fun add_term' (id, ct) ctxt = if in_table_raw_for_id ctxt (id, Thm.term_of ct) then ctxt elselet (* First add subterms. *) val t = Thm.term_of ct val imm_subterms = UtilLogic.list_subterms t val id_subs = map (fn t => (id, Thm.cterm_of ctxt t)) imm_subterms val ctxt' = ctxt |> fold add_term' id_subs |> add_term_raw (id, ct) in (* If t is already in table (just not at id), then we are done.Otherwisecomputeallindexedinfofort.
*) if in_table_raw ctxt t then ctxt' elselet (* Compute simplification and properties of t. Note we are doingthisinbox[](notid),soitdoesnotneedtobe recomputedifatermisaddedtoamoregeneralbox.
*) val simps = get_subterm_rewrite_info ctxt' ct in
ctxt' |> fold (add_contain ct) imm_subterms
|> fold update_simp simps
|> fold update_subsimp simps
|> add_all_equiv_raw ([], Thm.reflexive ct) end end
fun add_term (id, ct) ctxt = if in_table_raw_for_id ctxt (id, Thm.term_of ct) then ([], ctxt) else ctxt |> add_term' (id, ct) |> complete_table
fun add_term_list term_infos ctxt = case term_infos of
[] => ([], ctxt)
| (id, ct) :: rest => let val (edges, ctxt') = add_term (id, ct) ctxt val (edges', ctxt'') = add_term_list rest ctxt' in
(edges @ edges', ctxt'') end
(* First make sure t1 and t2 are in table. Add t1 == t2 to the table, andworkoutanyconsequences.Theresultisaconsistentrewrite table.
*) fun add_rewrite (id, eq_th) ctxt = let (* eq_th is meta-equality when between lambda terms. *) val meta_eq = if Util.is_meta_eq (Thm.prop_of eq_th) then eq_th else UtilLogic.to_meta_eq eq_th val (ct1, ct2) = meta_eq |> Thm.cprop_of |> Thm.dest_equals in if is_equiv id ctxt (ct1, ct2) then ([], ctxt) else
ctxt |> add_term' (id, ct1) |> add_term' (id, ct2)
|> add_rewrite_raw id meta_eq
|> complete_table
|> apfst (cons (id, meta_eq)) end
(* Returns the list of terms in ctxt' that is not in ctxt. *) fun get_new_terms (ctxt, ctxt') = let fun get_for_term ct =
(in_table_raw_ids ctxt' (Thm.term_of ct))
|> filter_out (fn id => in_table_raw_for_id ctxt (id, Thm.term_of ct))
|> map (rpair ct) in
maps get_for_term (get_all_terms ctxt') end
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.