src/Pure/context.ML
changeset 29093 1cc36c0ec9eb
parent 29069 c7ba485581ae
child 29095 a75f3ed534a0
equal deleted inserted replaced
29092:466a83cb6f5f 29093:1cc36c0ec9eb
    19   (*theory context*)
    19   (*theory context*)
    20   val parents_of: theory -> theory list
    20   val parents_of: theory -> theory list
    21   val ancestors_of: theory -> theory list
    21   val ancestors_of: theory -> theory list
    22   val theory_name: theory -> string
    22   val theory_name: theory -> string
    23   val is_stale: theory -> bool
    23   val is_stale: theory -> bool
    24   val PureN: string
       
    25   val is_draft: theory -> bool
    24   val is_draft: theory -> bool
    26   val reject_draft: theory -> theory
    25   val reject_draft: theory -> theory
    27   val exists_name: string -> theory -> bool
    26   val PureN: string
    28   val names_of: theory -> string list
    27   val display_names: theory -> string list
    29   val pretty_thy: theory -> Pretty.T
    28   val pretty_thy: theory -> Pretty.T
    30   val string_of_thy: theory -> string
    29   val string_of_thy: theory -> string
    31   val pprint_thy: theory -> pprint_args -> unit
    30   val pprint_thy: theory -> pprint_args -> unit
    32   val pprint_thy_ref: theory_ref -> pprint_args -> unit
    31   val pprint_thy_ref: theory_ref -> pprint_args -> unit
    33   val pretty_abbrev_thy: theory -> Pretty.T
    32   val pretty_abbrev_thy: theory -> Pretty.T
   142 (** datatype theory **)
   141 (** datatype theory **)
   143 
   142 
   144 datatype theory =
   143 datatype theory =
   145   Theory of
   144   Theory of
   146    (*identity*)
   145    (*identity*)
   147    {self: theory ref option,            (*dynamic self reference -- follows theory changes*)
   146    {self: theory ref option,      (*dynamic self reference -- follows theory changes*)
   148     id: serial * (string * int),        (*identifier/name of this theory node*)
   147     draft: bool,                  (*draft mode -- linear changes*)
   149     ids: (string * int) Inttab.table} * (*ancestors and checkpoints*)
   148     id: serial,                   (*identifier*)
   150    (*data*)
   149     ids: unit Inttab.table} *     (*cumulative identifiers of non-drafts -- symbolic body content*)
   151    Object.T Datatab.table *
   150    (*data*)                      
   152    (*ancestry*)
   151    Object.T Datatab.table *      
   153    {parents: theory list,               (*immediate predecessors*)
   152    (*ancestry*)                  
   154     ancestors: theory list} *           (*all predecessors*)
   153    {parents: theory list,         (*immediate predecessors*)
   155    (*history*)
   154     ancestors: theory list} *     (*all predecessors -- canonical reverse order*)
   156    {name: string,                       (*prospective name of finished theory*)
   155    (*history*)                   
   157     version: int};                      (*checkpoint counter*)
   156    {name: string,                 (*official theory name*)
       
   157     stage: int};                  (*checkpoint counter*)
   158 
   158 
   159 exception THEORY of string * theory list;
   159 exception THEORY of string * theory list;
   160 
   160 
   161 fun rep_theory (Theory args) = args;
   161 fun rep_theory (Theory args) = args;
   162 
   162 
   163 val identity_of = #1 o rep_theory;
   163 val identity_of = #1 o rep_theory;
   164 val data_of     = #2 o rep_theory;
   164 val data_of     = #2 o rep_theory;
   165 val ancestry_of = #3 o rep_theory;
   165 val ancestry_of = #3 o rep_theory;
   166 val history_of  = #4 o rep_theory;
   166 val history_of  = #4 o rep_theory;
   167 
   167 
   168 fun make_identity self id ids = {self = self, id = id, ids = ids};
   168 fun make_identity self draft id ids = {self = self, draft = draft, id = id, ids = ids};
   169 fun make_ancestry parents ancestors = {parents = parents, ancestors = ancestors};
   169 fun make_ancestry parents ancestors = {parents = parents, ancestors = ancestors};
   170 fun make_history name version = {name = name, version = version};
   170 fun make_history name stage = {name = name, stage = stage};
   171 
   171 
   172 val the_self = the o #self o identity_of;
   172 val the_self = the o #self o identity_of;
   173 val parents_of = #parents o ancestry_of;
   173 val parents_of = #parents o ancestry_of;
   174 val ancestors_of = #ancestors o ancestry_of;
   174 val ancestors_of = #ancestors o ancestry_of;
   175 val theory_name = #name o history_of;
   175 val theory_name = #name o history_of;
   176 
   176 
   177 
   177 
   178 (* staleness *)
   178 (* staleness *)
   179 
   179 
   180 fun eq_id ((i: int, _), (j, _)) = (i = j);
   180 fun eq_id (i: int, j) = i = j;
   181 
   181 
   182 fun is_stale
   182 fun is_stale
   183     (Theory ({self = SOME (ref (Theory ({id = id', ...}, _, _, _))), id, ...}, _, _, _)) =
   183     (Theory ({self = SOME (ref (Theory ({id = id', ...}, _, _, _))), id, ...}, _, _, _)) =
   184       not (eq_id (id, id'))
   184       not (eq_id (id, id'))
   185   | is_stale (Theory ({self = NONE, ...}, _, _, _)) = true;
   185   | is_stale (Theory ({self = NONE, ...}, _, _, _)) = true;
   186 
   186 
   187 fun vitalize (thy as Theory ({self = SOME r, ...}, _, _, _)) = (r := thy; thy)
   187 fun vitalize (thy as Theory ({self = SOME r, ...}, _, _, _)) = (r := thy; thy)
   188   | vitalize (thy as Theory ({self = NONE, id, ids}, data, ancestry, history)) =
   188   | vitalize (thy as Theory ({self = NONE, draft, id, ids}, data, ancestry, history)) =
   189       let
   189       let
   190         val r = ref thy;
   190         val r = ref thy;
   191         val thy' = Theory (make_identity (SOME r) id ids, data, ancestry, history);
   191         val thy' = Theory (make_identity (SOME r) draft id ids, data, ancestry, history);
   192       in r := thy'; thy' end;
   192       in r := thy'; thy' end;
   193 
   193 
   194 
   194 
   195 (* names *)
   195 (* draft mode *)
   196 
   196 
   197 val PureN = "Pure";
   197 val is_draft = #draft o identity_of;
   198 
       
   199 val draftN = "#";
       
   200 val draft_name = (draftN, ~1);
       
   201 
       
   202 fun draft_id (_, (name, _)) = (name = draftN);
       
   203 val is_draft = draft_id o #id o identity_of;
       
   204 
   198 
   205 fun reject_draft thy =
   199 fun reject_draft thy =
   206   if is_draft thy then raise THEORY ("Illegal draft theory -- stable checkpoint required", [thy])
   200   if is_draft thy then raise THEORY ("Illegal draft theory -- stable checkpoint required", [thy])
   207   else thy;
   201   else thy;
   208 
   202 
   209 fun exists_name name (thy as Theory ({id = (_, (a, _)), ids, ...}, _, _, _)) =
   203 
   210   name = theory_name thy orelse
   204 (* names *)
   211   name = a orelse
   205 
   212   Inttab.exists (fn (_, (b, _)) => b = name) ids;
   206 val PureN = "Pure";
   213 
   207 val draftN = "#";
   214 fun name_of (a, ~1) = a
   208 
   215   | name_of (a, i) = a ^ ":" ^ string_of_int i;
   209 fun display_names thy =
   216 
   210   let
   217 fun names_of (Theory ({id = (_, a), ids, ...}, _, _, _)) =
   211     val draft = if is_draft thy then [draftN] else [];
   218   rev (name_of a :: Inttab.fold (fn (_, (b, ~1)) => cons b | _ => I) ids []);
   212     val name =
   219 
   213       (case #stage (history_of thy) of
   220 fun pretty_thy thy =
   214         ~1 => theory_name thy
   221   Pretty.str_list "{" "}" (names_of thy @ (if is_stale thy then ["!"] else []));
   215       | n => theory_name thy ^ ":" ^ string_of_int n);
   222 
   216     val ancestor_names = map theory_name (ancestors_of thy);
       
   217     val stale = if is_stale thy then ["!"] else [];
       
   218   in rev (stale @ draft @ [name] @ ancestor_names) end;
       
   219 
       
   220 val pretty_thy = Pretty.str_list "{" "}" o display_names;
   223 val string_of_thy = Pretty.string_of o pretty_thy;
   221 val string_of_thy = Pretty.string_of o pretty_thy;
   224 val pprint_thy = Pretty.pprint o pretty_thy;
   222 val pprint_thy = Pretty.pprint o pretty_thy;
   225 
   223 
   226 fun pretty_abbrev_thy thy =
   224 fun pretty_abbrev_thy thy =
   227   let
   225   let
   228     val names = names_of thy;
   226     val names = display_names thy;
   229     val n = length names;
   227     val n = length names;
   230     val abbrev = if n > 5 then "..." :: List.drop (names, n - 5) else names;
   228     val abbrev = if n > 5 then "..." :: List.drop (names, n - 5) else names;
   231   in Pretty.str_list "{" "}" abbrev end;
   229   in Pretty.str_list "{" "}" abbrev end;
   232 
   230 
   233 val str_of_thy = Pretty.str_of o pretty_abbrev_thy;
   231 val str_of_thy = Pretty.str_of o pretty_abbrev_thy;
   250   end;
   248   end;
   251 
   249 
   252 val pprint_thy_ref = Pretty.pprint o pretty_thy o deref;
   250 val pprint_thy_ref = Pretty.pprint o pretty_thy o deref;
   253 
   251 
   254 
   252 
   255 (* consistency *)
   253 (* build ids *)
   256 
   254 
   257 fun check_insert id ids =
   255 fun insert_id draft id ids =
   258   if draft_id id orelse Inttab.defined ids (#1 id) then ids
   256   if draft then ids
   259   else if Inttab.exists (fn (_, a) => a = #2 id) ids then
   257   else Inttab.update (id, ()) ids;
   260     error ("Different versions of theory component " ^ quote (name_of (#2 id)))
   258 
   261   else Inttab.update id ids;
   259 fun merge_ids
   262 
   260     (Theory ({draft = draft1, id = id1, ids = ids1, ...}, _, _, _))
   263 fun check_merge
   261     (Theory ({draft = draft2, id = id2, ids = ids2, ...}, _, _, _)) =
   264     (Theory ({id = id1, ids = ids1, ...}, _, _, _))
   262   Inttab.merge (K true) (ids1, ids2)
   265     (Theory ({id = id2, ids = ids2, ...}, _, _, _)) =
   263   |> insert_id draft1 id1
   266   Inttab.fold check_insert ids2 ids1
   264   |> insert_id draft2 id2;
   267   |> check_insert id1
       
   268   |> check_insert id2;
       
   269 
   265 
   270 
   266 
   271 (* equality and inclusion *)
   267 (* equality and inclusion *)
   272 
   268 
   273 val eq_thy = eq_id o pairself (#id o identity_of);
   269 val eq_thy = eq_id o pairself (#id o identity_of);
   274 
   270 
   275 fun proper_subthy (Theory ({id, ...}, _, _, _), Theory ({ids, ...}, _, _, _)) =
   271 fun proper_subthy (Theory ({id, ...}, _, _, _), Theory ({ids, ...}, _, _, _)) =
   276   Inttab.defined ids (#1 id);
   272   Inttab.defined ids id;
   277 
   273 
   278 fun subthy thys = eq_thy thys orelse proper_subthy thys;
   274 fun subthy thys = eq_thy thys orelse proper_subthy thys;
   279 
   275 
   280 fun joinable (thy1, thy2) = subthy (thy1, thy2) orelse subthy (thy2, thy1);
   276 fun joinable (thy1, thy2) = subthy (thy1, thy2) orelse subthy (thy2, thy1);
       
   277 
       
   278 
       
   279 (* consistent ancestors *)
       
   280 
       
   281 fun extend_ancestors thy thys =
       
   282   if member eq_thy thys thy then raise THEORY ("Duplicate theory node", thy :: thys)
       
   283   else thy :: thys;
       
   284 
       
   285 fun extend_ancestors_of thy = extend_ancestors thy (ancestors_of thy);
       
   286 
       
   287 val merge_ancestors = merge (fn (thy1, thy2) =>
       
   288   eq_thy (thy1, thy2) orelse
       
   289     theory_name thy1 = theory_name thy2 andalso
       
   290       raise THEORY ("Inconsistent theory versions", [thy1, thy2]));
   281 
   291 
   282 
   292 
   283 (* trivial merge *)
   293 (* trivial merge *)
   284 
   294 
   285 fun merge (thy1, thy2) =
   295 fun merge (thy1, thy2) =
   286   if eq_thy (thy1, thy2) then thy1
   296   if eq_thy (thy1, thy2) then thy1
   287   else if proper_subthy (thy2, thy1) then thy1
   297   else if proper_subthy (thy2, thy1) then thy1
   288   else if proper_subthy (thy1, thy2) then thy2
   298   else if proper_subthy (thy1, thy2) then thy2
   289   else (check_merge thy1 thy2;
   299   else error (cat_lines ["Attempt to perform non-trivial merge of theories:",
   290     error (cat_lines ["Attempt to perform non-trivial merge of theories:",
   300     str_of_thy thy1, str_of_thy thy2]);
   291       str_of_thy thy1, str_of_thy thy2]));
       
   292 
   301 
   293 fun merge_refs (ref1, ref2) =
   302 fun merge_refs (ref1, ref2) =
   294   if ref1 = ref2 then ref1
   303   if ref1 = ref2 then ref1
   295   else check_thy (merge (deref ref1, deref ref2));
   304   else check_thy (merge (deref ref1, deref ref2));
   296 
   305 
   298 
   307 
   299 (** build theories **)
   308 (** build theories **)
   300 
   309 
   301 (* primitives *)
   310 (* primitives *)
   302 
   311 
   303 fun create_thy name self id ids data ancestry history =
   312 fun create_thy self draft ids data ancestry history =
   304   let
   313   let val identity = make_identity self draft (serial ()) ids;
   305     val {version, ...} = history;
   314   in vitalize (Theory (identity, data, ancestry, history)) end;
   306     val ids' = check_insert id ids;
   315 
   307     val id' = (serial (), name);
   316 fun change_thy draft' f thy =
   308     val _ = check_insert id' ids';
   317   let
   309     val identity' = make_identity self id' ids';
   318     val Theory ({self, draft, id, ids}, data, ancestry, history) = thy;
   310   in vitalize (Theory (identity', data, ancestry, history)) end;
       
   311 
       
   312 fun change_thy name f thy =
       
   313   let
       
   314     val Theory ({self, id, ids}, data, ancestry, history) = thy;
       
   315     val (self', data', ancestry') =
   319     val (self', data', ancestry') =
   316       if is_draft thy then (self, data, ancestry)    (*destructive change!*)
   320       if draft then (self, data, ancestry)    (*destructive change!*)
   317       else if #version history > 0
   321       else if #stage history > 0
   318       then (NONE, copy_data data, ancestry)
   322       then (NONE, copy_data data, ancestry)
   319       else (NONE, extend_data data, make_ancestry [thy] (thy :: #ancestors ancestry));
   323       else (NONE, extend_data data, make_ancestry [thy] (extend_ancestors_of thy));
       
   324     val ids' = insert_id draft id ids;
   320     val data'' = f data';
   325     val data'' = f data';
   321     val thy' = NAMED_CRITICAL "theory" (fn () =>
   326     val thy' = NAMED_CRITICAL "theory" (fn () =>
   322       (check_thy thy; create_thy name self' id ids data'' ancestry' history));
   327       (check_thy thy; create_thy self' draft' ids' data'' ancestry' history));
   323   in thy' end;
   328   in thy' end;
   324 
   329 
   325 fun name_thy name = change_thy name I;
   330 val name_thy = change_thy false I;
   326 val modify_thy = change_thy draft_name;
   331 val extend_thy = change_thy true I;
   327 val extend_thy = modify_thy I;
   332 val modify_thy = change_thy true;
   328 
   333 
   329 fun copy_thy thy =
   334 fun copy_thy thy =
   330   let
   335   let
   331     val Theory ({id, ids, ...}, data, ancestry, history) = thy;
   336     val Theory ({draft, id, ids, ...}, data, ancestry, history) = thy;
       
   337     val ids' = insert_id draft id ids;
   332     val data' = copy_data data;
   338     val data' = copy_data data;
   333     val thy' = NAMED_CRITICAL "theory" (fn () =>
   339     val thy' = NAMED_CRITICAL "theory" (fn () =>
   334       (check_thy thy; create_thy draft_name NONE id ids data' ancestry history));
   340       (check_thy thy; create_thy NONE true ids' data' ancestry history));
   335   in thy' end;
   341   in thy' end;
   336 
   342 
   337 val pre_pure_thy = create_thy draft_name NONE (serial (), draft_name) Inttab.empty
   343 val pre_pure_thy = create_thy NONE true Inttab.empty
   338   Datatab.empty (make_ancestry [] []) (make_history PureN 0);
   344   Datatab.empty (make_ancestry [] []) (make_history PureN 0);
   339 
   345 
   340 
   346 
   341 (* named theory nodes *)
   347 (* named theory nodes *)
   342 
   348 
   343 fun merge_thys pp (thy1, thy2) =
   349 fun merge_thys pp (thy1, thy2) =
   344   let
   350   let
   345     val ids = check_merge thy1 thy2;
   351     val ids = merge_ids thy1 thy2;
   346     val data = merge_data (pp thy1) (data_of thy1, data_of thy2);
   352     val data = merge_data (pp thy1) (data_of thy1, data_of thy2);
   347     val ancestry = make_ancestry [] [];
   353     val ancestry = make_ancestry [] [];
   348     val history = make_history "" 0;
   354     val history = make_history "" 0;
   349     val thy' = NAMED_CRITICAL "theory" (fn () =>
   355     val thy' = NAMED_CRITICAL "theory" (fn () =>
   350      (check_thy thy1; check_thy thy2;
   356      (check_thy thy1; check_thy thy2; create_thy NONE true ids data ancestry history));
   351       create_thy draft_name NONE (serial (), draft_name) ids data ancestry history));
       
   352   in thy' end;
   357   in thy' end;
   353 
   358 
   354 fun maximal_thys thys =
   359 fun maximal_thys thys =
   355   thys |> filter_out (fn thy => exists (fn thy' => proper_subthy (thy, thy')) thys);
   360   thys |> filter_out (fn thy => exists (fn thy' => proper_subthy (thy, thy')) thys);
   356 
   361 
   357 fun begin_thy pp name imports =
   362 fun begin_thy pp name imports =
   358   if name = draftN then error ("Illegal theory name: " ^ quote draftN)
   363   if name = "" orelse name = draftN then error ("Bad theory name: " ^ quote name)
   359   else
   364   else
   360     let
   365     let
   361       val parents = maximal_thys (distinct eq_thy imports);
   366       val parents = maximal_thys (distinct eq_thy imports);
   362       val ancestors = distinct eq_thy (parents @ maps ancestors_of parents);
   367       val ancestors =
   363       val Theory ({id, ids, ...}, data, _, _) =
   368         Library.foldl merge_ancestors ([], map ancestors_of parents)
       
   369         |> fold extend_ancestors parents;
       
   370 
       
   371       val Theory ({ids, ...}, data, _, _) =
   364         (case parents of
   372         (case parents of
   365           [] => error "No parent theories"
   373           [] => error "No parent theories"
   366         | [thy] => extend_thy thy
   374         | [thy] => extend_thy thy
   367         | thy :: thys => Library.foldl (merge_thys pp) (thy, thys));
   375         | thy :: thys => Library.foldl (merge_thys pp) (thy, thys));
       
   376 
   368       val ancestry = make_ancestry parents ancestors;
   377       val ancestry = make_ancestry parents ancestors;
   369       val history = make_history name 0;
   378       val history = make_history name 0;
   370       val thy' = NAMED_CRITICAL "theory" (fn () =>
   379       val thy' = NAMED_CRITICAL "theory" (fn () =>
   371         (map check_thy imports; create_thy draft_name NONE id ids data ancestry history));
   380         (map check_thy imports; create_thy NONE true ids data ancestry history));
   372     in thy' end;
   381     in thy' end;
   373 
   382 
   374 
   383 
   375 (* persistent checkpoints *)
   384 (* history stages *)
       
   385 
       
   386 fun history_stage f thy =
       
   387   let
       
   388     val {name, stage} = history_of thy;
       
   389     val _ = stage = ~1 andalso raise THEORY ("Theory already finished", [thy]);
       
   390     val history' = make_history name (f stage);
       
   391     val thy' as Theory (identity', data', ancestry', _) = name_thy thy;
       
   392     val thy'' = NAMED_CRITICAL "theory" (fn () =>
       
   393       (check_thy thy'; vitalize (Theory (identity', data', ancestry', history'))));
       
   394   in thy'' end;
   376 
   395 
   377 fun checkpoint_thy thy =
   396 fun checkpoint_thy thy =
   378   if not (is_draft thy) then thy
   397   if is_draft thy then history_stage (fn stage => stage + 1) thy
   379   else
   398   else thy;
   380     let
   399 
   381       val {name, version} = history_of thy;
   400 val finish_thy = history_stage (fn _ => ~1);
   382       val thy' as Theory (identity', data', ancestry', _) = name_thy (name, version) thy;
       
   383       val history' = make_history name (version + 1);
       
   384       val thy'' = NAMED_CRITICAL "theory" (fn () =>
       
   385         (check_thy thy'; vitalize (Theory (identity', data', ancestry', history'))));
       
   386     in thy'' end;
       
   387 
       
   388 fun finish_thy thy = NAMED_CRITICAL "theory" (fn () =>
       
   389   let
       
   390     val name = theory_name thy;
       
   391     val Theory (identity', data', ancestry', _) = name_thy (name, ~1) thy;
       
   392     val history' = make_history name 0;
       
   393     val thy' = vitalize (Theory (identity', data', ancestry', history'));
       
   394   in thy' end);
       
   395 
   401 
   396 
   402 
   397 (* theory data *)
   403 (* theory data *)
   398 
   404 
   399 structure TheoryData =
   405 structure TheoryData =