# HG changeset patch # User wenzelm # Date 1682018795 -7200 # Node ID 655bd3b0671bd1198b5e98558c1bb146d4f6a57e # Parent 186bd4012b7835fe6c43d4267fbe07051b044637 support n-ary merge theory data; less redundant use of ids and stages; diff -r 186bd4012b78 -r 655bd3b0671b src/HOL/ex/Join_Theory.thy --- a/src/HOL/ex/Join_Theory.thy Thu Apr 20 15:26:34 2023 +0200 +++ b/src/HOL/ex/Join_Theory.thy Thu Apr 20 21:26:35 2023 +0200 @@ -35,7 +35,7 @@ setup \ fn thy => let val forked_thys = Par_List.map (fn i => Named_Target.theory_map (spec i) thy) (1 upto 10) - in Theory.join_theory forked_thys end + in Context.join_thys forked_thys end \ term test1 diff -r 186bd4012b78 -r 655bd3b0671b src/Pure/Isar/locale.ML --- a/src/Pure/Isar/locale.ML Thu Apr 20 15:26:34 2023 +0200 +++ b/src/Pure/Isar/locale.ML Thu Apr 20 21:26:35 2023 +0200 @@ -355,8 +355,9 @@ unique registration serial points to mixin list*) type T = reg Idtab.table * mixins; val empty: T = (Idtab.empty, Inttab.empty); - fun merge old_thys = + fun merge args = let + val ctxt0 = Syntax.init_pretty_global (#1 (hd args)); fun recursive_merge ((regs1, mixins1), (regs2, mixins2)) : T = (Idtab.merge eq_reg (regs1, regs2), merge_mixins (mixins1, mixins2)) handle Idtab.DUP id => @@ -373,9 +374,9 @@ val _ = warning ("Removed duplicate interpretation after retrieving its mixins" ^ Position.here_list [#pos reg1, #pos reg2] ^ ":\n " ^ - Pretty.string_of (pretty_reg_inst (Syntax.init_pretty_global (#1 old_thys)) [] id)); + Pretty.string_of (pretty_reg_inst ctxt0 [] id)); in recursive_merge ((regs1, mixins1), (regs2', mixins2')) end; - in recursive_merge end; + in Library.foldl1 recursive_merge (map #2 args) end; ); structure Local_Registrations = Proof_Data diff -r 186bd4012b78 -r 655bd3b0671b src/Pure/axclass.ML --- a/src/Pure/axclass.ML Thu Apr 20 15:26:34 2023 +0200 +++ b/src/Pure/axclass.ML Thu Apr 20 21:26:35 2023 +0200 @@ -74,6 +74,8 @@ (*constant name ~> type constructor ~> (constant name, equation)*) (string * string) Symtab.table (*constant name ~> (constant name, type constructor)*)}; +fun rep_data (Data args) = args; + fun make_data (axclasses, params, inst_params) = Data {axclasses = axclasses, params = params, inst_params = inst_params}; @@ -81,22 +83,23 @@ ( type T = data; val empty = make_data (Symtab.empty, [], (Symtab.empty, Symtab.empty)); - fun merge old_thys - (Data {axclasses = axclasses1, params = params1, inst_params = inst_params1}, - Data {axclasses = axclasses2, params = params2, inst_params = inst_params2}) = + fun merge args = let - val old_ctxt = Syntax.init_pretty_global (fst old_thys); + val ctxt0 = Syntax.init_pretty_global (#1 (hd args)); - val axclasses' = Symtab.merge (K true) (axclasses1, axclasses2); - val params' = + fun merge_params (params1, params2) = if null params1 then params2 else - fold_rev (fn p => if member (op =) params1 p then I else add_param old_ctxt p) + fold_rev (fn p => if member (op =) params1 p then I else add_param ctxt0 p) params2 params1; - val inst_params' = + fun merge_inst_params (inst_params1, inst_params2) = (Symtab.join (K (Symtab.merge (K true))) (#1 inst_params1, #1 inst_params2), Symtab.merge (K true) (#2 inst_params1, #2 inst_params2)); + + val axclasses' = Library.foldl1 (Symtab.merge (K true)) (map (#axclasses o rep_data o #2) args); + val params' = Library.foldl1 merge_params (map (#params o rep_data o #2) args); + val inst_params' = Library.foldl1 merge_inst_params (map (#inst_params o rep_data o #2) args); in make_data (axclasses', params', inst_params') end; ); @@ -116,11 +119,11 @@ map_data (fn (axclasses, params, inst_params) => (axclasses, params, f inst_params)); -val rep_data = Data.get #> (fn Data args => args); +val rep_theory_data = Data.get #> rep_data; -val axclasses_of = #axclasses o rep_data; -val params_of = #params o rep_data; -val inst_params_of = #inst_params o rep_data; +val axclasses_of = #axclasses o rep_theory_data; +val params_of = #params o rep_theory_data; +val inst_params_of = #inst_params o rep_theory_data; (* axclasses with parameters *) diff -r 186bd4012b78 -r 655bd3b0671b src/Pure/context.ML --- a/src/Pure/context.ML Thu Apr 20 15:26:34 2023 +0200 +++ b/src/Pure/context.ML Thu Apr 20 21:26:35 2023 +0200 @@ -51,7 +51,7 @@ val subthy: theory * theory -> bool val trace_theories: bool Unsynchronized.ref val theories_trace: unit -> {active_positions: Position.T list, active: int, total: int} - val join_thys: theory * theory -> theory + val join_thys: theory list -> theory val begin_thy: string -> theory list -> theory val finish_thy: theory -> theory val theory_data_sizeof1: theory -> (Position.T * int) list @@ -95,7 +95,7 @@ include CONTEXT structure Theory_Data: sig - val declare: Position.T -> Any.T -> (theory * theory -> Any.T * Any.T -> Any.T) -> serial + val declare: Position.T -> Any.T -> ((theory * Any.T) list -> Any.T) -> serial val get: serial -> (Any.T -> 'a) -> theory -> 'a val put: serial -> ('a -> Any.T) -> 'a -> theory -> theory end @@ -118,6 +118,19 @@ (** datatype theory **) +(* implicit state *) + +type state = {stage: int} Synchronized.var; + +fun make_state () : state = + Synchronized.var "Context.state" {stage = 0}; + +fun next_stage (state: state) = + Synchronized.change_result state (fn {stage} => (stage + 1, {stage = stage + 1})); + + +(* theory_id *) + abstype theory_id = Theory_Id of {id: serial, (*identifier*) @@ -131,13 +144,16 @@ end; + +(* theory *) + datatype theory = Theory of + (*allocation state*) + state * (*identity*) {theory_id: theory_id, token: Position.T Unsynchronized.ref} * - (*allocation state*) - {next_stage: unit -> int} * (*ancestry*) {parents: theory list, (*immediate predecessors*) ancestors: theory list} * (*all predecessors -- canonical reverse order*) @@ -148,16 +164,13 @@ fun rep_theory (Theory args) = args; -val theory_identity = #1 o rep_theory; +val state_of = #1 o rep_theory; +val theory_identity = #2 o rep_theory; val theory_id = #theory_id o theory_identity; val identity_of = rep_theory_id o theory_id; -val state_of = #2 o rep_theory; val ancestry_of = #3 o rep_theory; val data_of = #4 o rep_theory; -fun make_state () = {next_stage = Counter.make ()}; -fun next_stage {next_stage: unit -> int} = next_stage (); - fun make_ancestry parents ancestors = {parents = parents, ancestors = ancestors}; fun stage_final stage = stage = 0; @@ -214,17 +227,11 @@ else error ("Unfinished theory " ^ quote name); -(* build ids *) +(* identity *) -val merge_ids = - apply2 identity_of #> - (fn ({id = id1, ids = ids1, ...}, {id = id2, ids = ids2, ...}) => - Intset.merge (ids1, ids2) - |> Intset.insert id1 - |> Intset.insert id2); - - -(* equality and inclusion *) +fun merge_ids thys = + fold (identity_of #> (fn {id, ids, ...} => fn acc => Intset.merge (acc, ids) |> Intset.insert id)) + thys Intset.empty; val eq_thy_id = op = o apply2 (#id o rep_theory_id); val eq_thy = op = o apply2 (#id o identity_of); @@ -250,6 +257,11 @@ val merge_ancestors = merge eq_thy_consistent; +val eq_ancestry = + apply2 ancestry_of #> + (fn ({parents, ancestors}, {parents = parents', ancestors = ancestors'}) => + eq_list eq_thy (parents, parents') andalso eq_list eq_thy (ancestors, ancestors')); + (** theory data **) @@ -263,24 +275,25 @@ type kind = {pos: Position.T, empty: Any.T, - merge: theory * theory -> Any.T * Any.T -> Any.T}; + merge: (theory * Any.T) list -> Any.T}; val kinds = Synchronized.var "Theory_Data" (Datatab.empty: kind Datatab.table); -fun invoke name f k x = +fun the_kind k = (case Datatab.lookup (Synchronized.value kinds) k of - SOME kind => - if ! timing andalso name <> "" then - Timing.cond_timeit true ("Theory_Data." ^ name ^ Position.here (#pos kind)) - (fn () => f kind x) - else f kind x + SOME kind => kind | NONE => raise Fail "Invalid theory data identifier"); in -fun invoke_pos k = invoke "" (K o #pos) k (); -fun invoke_empty k = invoke "" (K o #empty) k (); -fun invoke_merge thys = invoke "merge" (fn kind => #merge kind thys); +val invoke_pos = #pos o the_kind; +val invoke_empty = #empty o the_kind; + +fun invoke_merge kind args = + if ! timing then + Timing.cond_timeit true ("Theory_Data.merge" ^ Position.here (#pos kind)) + (fn () => #merge kind args) + else #merge kind args; fun declare_data pos empty merge = let @@ -289,12 +302,23 @@ val _ = Synchronized.change kinds (Datatab.update (k, kind)); in k end; +fun lookup_data k thy = Datatab.lookup (data_of thy) k; + fun get_data k thy = - (case Datatab.lookup (data_of thy) k of + (case lookup_data k thy of SOME x => x | NONE => invoke_empty k); -fun merge_data thys = Datatab.join (invoke_merge thys); +fun merge_data [] = Datatab.empty + | merge_data [thy] = data_of thy + | merge_data thys = + let + fun merge (k, kind) data = + (case map_filter (fn thy => lookup_data k thy |> Option.map (pair thy)) thys of + [] => data + | [(_, x)] => Datatab.default (k, x) data + | args => Datatab.update (k, invoke_merge kind args) data); + in Datatab.fold merge (Synchronized.value kinds) (data_of (hd thys)) end; end; @@ -336,11 +360,11 @@ total = length trace} end; -fun create_thy ids name stage state ancestry data = +fun create_thy state ids name stage ancestry data = let val theory_id = make_theory_id {id = serial (), ids = ids, name = name, stage = stage}; - val token = make_token (); - in Theory ({theory_id = theory_id, token = token}, state, ancestry, data) end; + val identity = {theory_id = theory_id, token = make_token ()}; + in Theory (state, identity, ancestry, data) end; end; @@ -351,105 +375,77 @@ let val state = make_state (); val stage = next_stage state; - in create_thy Intset.empty PureN stage state (make_ancestry [] []) Datatab.empty end; + in create_thy state Intset.empty PureN stage (make_ancestry [] []) Datatab.empty end; local fun change_thy finish f thy = let - val {id, ids, name, stage} = identity_of thy; - val Theory (_, state, ancestry, data) = thy; + val {name, stage, ...} = identity_of thy; + val Theory (state, _, ancestry, data) = thy; val ancestry' = if stage_final stage then make_ancestry [thy] (extend_ancestors thy (ancestors_of thy)) else ancestry; - val ids' = Intset.insert id ids; + val ids' = merge_ids [thy]; val stage' = if finish then 0 else next_stage state; val data' = f data; - in create_thy ids' name stage' state ancestry' data' end; + in create_thy state ids' name stage' ancestry' data' end; in val update_thy = change_thy false; -val extend_thy = change_thy false I; val finish_thy = change_thy true I; end; -(* join: anonymous theory nodes *) - -local - -fun bad_join (thy1, thy2) = raise THEORY ("Cannot join theories", [thy1, thy2]); +(* join: unfinished theory nodes *) -fun join_stage (thy1, thy2) = - apply2 identity_of (thy1, thy2) |> - (fn ({name, stage, ...}, {name = name', stage = stage', ...}) => - if name <> name' orelse stage_final stage orelse stage_final stage' - then bad_join (thy1, thy2) - else - let val state = state_of thy1 - in {name = name, stage = next_stage state, state = state} end) +fun join_thys [] = raise List.Empty + | join_thys thys = + let + val thy0 = hd thys; + val name0 = theory_long_name thy0; + val state0 = state_of thy0; -fun join_ancestry thys = - apply2 ancestry_of thys |> - (fn (ancestry as {parents, ancestors}, {parents = parents', ancestors = ancestors'}) => - if eq_list eq_thy (parents, parents') andalso eq_list eq_thy (ancestors, ancestors') - then ancestry else bad_join thys); - -in + fun ok thy = + not (theory_id_final (theory_id thy)) andalso + theory_long_name thy = name0 andalso + eq_ancestry (thy0, thy); + val _ = + (case filter_out ok thys of + [] => () + | bad => raise THEORY ("Cannot join theories", bad)); -fun join_thys thys = - let - val ids = merge_ids thys; - val {name, stage, state} = join_stage thys; - val ancestry = join_ancestry thys; - val data = merge_data thys (apply2 data_of thys); - in create_thy ids name stage state ancestry data end; - -end; + val stage = next_stage state0; + val ids = merge_ids thys; + val data = merge_data thys; + in create_thy state0 ids name0 stage (ancestry_of thy0) data end; -(* merge: named theory nodes *) - -local +(* merge: finished theory nodes *) -fun merge_thys thys = - let - val ids = merge_ids thys; - val state = state_of (#1 thys); - val ancestry = make_ancestry [] []; - val data = merge_data thys (apply2 data_of thys); - in create_thy ids "" 0 state ancestry data end; - -fun maximal_thys thys = - thys |> filter_out (fn thy => exists (fn thy' => proper_subthy (thy, thy')) thys); - -in +fun make_parents thys = + let val thys' = distinct eq_thy thys + in thys' |> filter_out (fn thy => exists (fn thy' => proper_subthy (thy, thy')) thys') end; fun begin_thy name imports = if name = "" then error ("Bad theory name: " ^ quote name) + else if null imports then error "Missing theory imports" else let - val parents = maximal_thys (distinct eq_thy imports); + val parents = make_parents imports; val ancestors = - Library.foldl merge_ancestors ([], map ancestors_of parents) + Library.foldl1 merge_ancestors (map ancestors_of parents) |> fold extend_ancestors parents; - - val thy0 = - (case parents of - [] => error "Missing theory imports" - | [thy] => extend_thy thy - | thy :: thys => Library.foldl merge_thys (thy, thys)); - val ids = #ids (identity_of thy0); + val ancestry = make_ancestry parents ancestors; val state = make_state (); val stage = next_stage state; - val ancestry = make_ancestry parents ancestors; - in create_thy ids name stage state ancestry (data_of thy0) |> tap finish_thy end; - -end; + val ids = merge_ids parents; + val data = merge_data parents; + in create_thy state ids name stage ancestry data |> tap finish_thy end; (* theory data *) @@ -641,7 +637,7 @@ sig type T val empty: T - val merge: theory * theory -> T * T -> T + val merge: (theory * T) list -> T end; signature THEORY_DATA_ARGS = @@ -670,7 +666,7 @@ Context.Theory_Data.declare pos (Data Data.empty) - (fn thys => fn (Data x1, Data x2) => Data (Data.merge thys (x1, x2))) + (Data o Data.merge o map (fn (thy, Data x) => (thy, x))) end; val get = Context.Theory_Data.get kind (fn Data x => x); @@ -684,7 +680,7 @@ ( type T = Data.T; val empty = Data.empty; - fun merge _ = Data.merge; + fun merge args = Library.foldl (fn (a, (_, b)) => Data.merge (a, b)) (#2 (hd args), tl args) ); diff -r 186bd4012b78 -r 655bd3b0671b src/Pure/sign.ML --- a/src/Pure/sign.ML Thu Apr 20 15:26:34 2023 +0200 +++ b/src/Pure/sign.ML Thu Apr 20 21:26:35 2023 +0200 @@ -129,24 +129,23 @@ tsig: Type.tsig, (*order-sorted signature of types*) consts: Consts.T}; (*polymorphic constants*) +fun rep_sign (Sign args) = args; fun make_sign (syn, tsig, consts) = Sign {syn = syn, tsig = tsig, consts = consts}; structure Data = Theory_Data' ( type T = sign; val empty = make_sign (Syntax.empty_syntax, Type.empty_tsig, Consts.empty); - fun merge old_thys (sign1, sign2) = + fun merge args = let - val Sign {syn = syn1, tsig = tsig1, consts = consts1} = sign1; - val Sign {syn = syn2, tsig = tsig2, consts = consts2} = sign2; - - val syn = Syntax.merge_syntax (syn1, syn2); - val tsig = Type.merge_tsig (Context.Theory (fst old_thys)) (tsig1, tsig2); - val consts = Consts.merge (consts1, consts2); - in make_sign (syn, tsig, consts) end; + val context0 = Context.Theory (#1 (hd args)); + val syn' = Library.foldl1 Syntax.merge_syntax (map (#syn o rep_sign o #2) args); + val tsig' = Library.foldl1 (Type.merge_tsig context0) (map (#tsig o rep_sign o #2) args); + val consts' = Library.foldl1 Consts.merge (map (#consts o rep_sign o #2) args); + in make_sign (syn', tsig', consts') end; ); -fun rep_sg thy = Data.get thy |> (fn Sign args => args); +val rep_sg = rep_sign o Data.get; fun map_sign f = Data.map (fn Sign {syn, tsig, consts} => make_sign (f (syn, tsig, consts))); diff -r 186bd4012b78 -r 655bd3b0671b src/Pure/theory.ML --- a/src/Pure/theory.ML Thu Apr 20 15:26:34 2023 +0200 +++ b/src/Pure/theory.ML Thu Apr 20 21:26:35 2023 +0200 @@ -22,7 +22,6 @@ val defs_of: theory -> Defs.T val at_begin: (theory -> theory option) -> theory -> theory val at_end: (theory -> theory option) -> theory -> theory - val join_theory: theory list -> theory val begin_theory: string * Position.T -> theory list -> theory val end_theory: theory -> theory val add_axiom: Proof.context -> binding * term -> theory -> theory @@ -83,6 +82,8 @@ defs: Defs.T, wrappers: wrapper list * wrapper list}; +fun rep_thy (Thy args) = args; + fun make_thy (pos, id, axioms, defs, wrappers) = Thy {pos = pos, id = id, axioms = axioms, defs = defs, wrappers = wrappers}; @@ -90,19 +91,22 @@ ( type T = thy; val empty = make_thy (Position.none, 0, Name_Space.empty_table Markup.axiomN, Defs.empty, ([], [])); - fun merge old_thys (thy1, thy2) = + fun merge args = let - val Thy {pos, id, axioms = axioms1, defs = defs1, wrappers = (bgs1, ens1)} = thy1; - val Thy {pos = _, id = _, axioms = axioms2, defs = defs2, wrappers = (bgs2, ens2)} = thy2; + val thy0 = #1 (hd args); + val {pos, id, ...} = rep_thy (#2 (hd args)); - val axioms' = Name_Space.merge_tables (axioms1, axioms2); - val defs' = Defs.merge (Defs.global_context (fst old_thys)) (defs1, defs2); - val bgs' = Library.merge (eq_snd op =) (bgs1, bgs2); - val ens' = Library.merge (eq_snd op =) (ens1, ens2); + val merge_defs = Defs.merge (Defs.global_context thy0); + val merge_wrappers = Library.merge (eq_snd op =); + + val axioms' = Library.foldl1 Name_Space.merge_tables (map (#axioms o rep_thy o #2) args); + val defs' = Library.foldl1 merge_defs (map (#defs o rep_thy o #2) args); + val bgs' = Library.foldl1 merge_wrappers (map (#1 o #wrappers o rep_thy o #2) args); + val ens' = Library.foldl1 merge_wrappers (map (#2 o #wrappers o rep_thy o #2) args); in make_thy (pos, id, axioms', defs', (bgs', ens')) end; ); -fun rep_theory thy = Thy.get thy |> (fn Thy args => args); +val rep_theory = rep_thy o Thy.get; fun map_thy f = Thy.map (fn (Thy {pos, id, axioms, defs, wrappers}) => make_thy (f (pos, id, axioms, defs, wrappers))); @@ -162,13 +166,6 @@ val defs_of = #defs o rep_theory; -(* join theory *) - -fun join_theory [] = raise List.Empty - | join_theory [thy] = thy - | join_theory thys = foldl1 Context.join_thys thys; - - (* begin/end theory *) val begin_wrappers = rev o #1 o #wrappers o rep_theory;