diff options
Diffstat (limited to 'library/lib.ml')
-rw-r--r-- | library/lib.ml | 233 |
1 files changed, 171 insertions, 62 deletions
diff --git a/library/lib.ml b/library/lib.ml index 4a4e90c1..ce3d2520 100644 --- a/library/lib.ml +++ b/library/lib.ml @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: lib.ml 10269 2007-10-29 11:09:43Z notin $ *) +(* $Id: lib.ml 10982 2008-05-24 14:32:25Z herbelin $ *) open Pp open Util @@ -22,9 +22,11 @@ type node = | Leaf of obj | CompilingLibrary of object_prefix | OpenedModule of bool option * object_prefix * Summary.frozen + | ClosedModule of library_segment | OpenedModtype of object_prefix * Summary.frozen + | ClosedModtype of library_segment | OpenedSection of object_prefix * Summary.frozen - | ClosedSection + | ClosedSection of library_segment | FrozenState of Summary.frozen and library_entry = object_name * node @@ -60,7 +62,11 @@ let classify_segment seg = clean ((id,o')::substl, keepl, anticipl) stk | Anticipate o' -> clean (substl, keepl, o'::anticipl) stk) - | (oname,ClosedSection) :: stk -> clean acc stk + | (_,ClosedSection _) :: stk -> clean acc stk + (* LEM; TODO: Understand what this does and see if what I do is the + correct thing for ClosedMod(ule|type) *) + | (_,ClosedModule _) :: stk -> clean acc stk + | (_,ClosedModtype _) :: stk -> clean acc stk | (_,OpenedSection _) :: _ -> error "there are still opened sections" | (_,OpenedModule _) :: _ -> error "there are still opened modules" | (_,OpenedModtype _) :: _ -> error "there are still opened module types" @@ -92,11 +98,15 @@ let library_dp () = module path and relative section path *) let path_prefix = ref initial_prefix - let cwd () = fst !path_prefix let make_path id = Libnames.make_path (cwd ()) id +let path_of_include () = + let dir = Names.repr_dirpath (cwd ()) in + let new_dir = List.tl dir in + let id = List.hd dir in + Libnames.make_path (Names.make_dirpath new_dir) id let current_prefix () = snd !path_prefix @@ -150,18 +160,32 @@ let find_split_p p = in find !lib_stk -let split_lib sp = +let split_lib_gen test = let rec collect after equal = function - | ((sp',_) as hd)::before -> - if sp = sp' then collect after (hd::equal) before else after,equal,hd::before - | [] -> after,equal,[] + | hd::strict_before as before -> + if test hd then collect after (hd::equal) strict_before else after,equal,before + | [] as before -> after,equal,before in let rec findeq after = function - | ((sp',_) as hd)::before -> - if sp = sp' then collect after [hd] before else findeq (hd::after) before - | [] -> error "no such entry" - in - findeq [] !lib_stk + | hd :: before -> + if test hd + then Some (collect after [hd] before) + else (match hd with + | (sp,ClosedModule seg) + | (sp,ClosedModtype seg) + | (sp,ClosedSection seg) -> + (match findeq after seg with + | None -> findeq (hd::after) before + | Some (sub_after,sub_equal,sub_before) -> + Some (sub_after, sub_equal, (List.append sub_before before))) + | _ -> findeq (hd::after) before) + | [] -> None + in + match findeq [] !lib_stk with + | None -> error "no such entry" + | Some r -> r + +let split_lib sp = split_lib_gen (fun x -> (fst x) = sp) (* Adding operations. *) @@ -190,9 +214,9 @@ let add_leaf id obj = add_entry oname (Leaf obj); oname -let add_discharged_leaf id obj = +let add_discharged_leaf id varinfo obj = let oname = make_oname id in - let newobj = rebuild_object obj in + let newobj = rebuild_object (varinfo, obj) in cache_object (oname,newobj); add_entry oname (Leaf newobj) @@ -216,12 +240,25 @@ let add_frozen_state () = (* Modules. *) + let is_something_opened = function (_,OpenedSection _) -> true | (_,OpenedModule _) -> true | (_,OpenedModtype _) -> true | _ -> false + +let current_mod_id () = + try match find_entry_p is_something_opened with + | oname,OpenedModule (_,_,nametab) -> + basename (fst oname) + | oname,OpenedModtype (_,nametab) -> + basename (fst oname) + | _ -> error "you are not in a module" + with Not_found -> + error "no opened modules" + + let start_module export id mp nametab = let dir = extend_dirpath (fst !path_prefix) id in let prefix = dir,(mp,empty_dirpath) in @@ -253,9 +290,15 @@ let end_module id = with Not_found -> error "no opened modules" in - let (after,_,before) = split_lib oname in + let (after,modopening,before) = split_lib oname in lib_stk := before; + add_entry (make_oname id) (ClosedModule (List.rev_append after (List.rev modopening))); let prefix = !path_prefix in + (* LEM: This module business seems more complicated than sections; + shouldn't a backtrack into a closed module also do something + with global.ml, given that closing a module does? + TODO + *) recalc_path_prefix (); (* add_frozen_state must be called after processing the module, because we cannot recache interactive modules *) @@ -292,8 +335,9 @@ let end_modtype id = with Not_found -> error "no opened module types" in - let (after,_,before) = split_lib sp in + let (after,modtypeopening,before) = split_lib sp in lib_stk := before; + add_entry (make_oname id) (ClosedModtype (List.rev_append after (List.rev modtypeopening))); let dir = !path_prefix in recalc_path_prefix (); (* add_frozen_state must be called after processing the module type. @@ -396,18 +440,19 @@ let what_is_opened () = find_entry_p is_something_opened type abstr_list = Sign.named_context Cmap.t * Sign.named_context KNmap.t let sectab = - ref ([] : (identifier list * Cooking.work_list * abstr_list) list) + ref ([] : ((identifier * bool * Term.types option) list * Cooking.work_list * abstr_list) list) let add_section () = sectab := ([],(Cmap.empty,KNmap.empty),(Cmap.empty,KNmap.empty)) :: !sectab -let add_section_variable id = +let add_section_variable id impl keep = match !sectab with | [] -> () (* because (Co-)Fixpoint temporarily uses local vars *) - | (vars,repl,abs)::sl -> sectab := (id::vars,repl,abs)::sl + | (vars,repl,abs)::sl -> sectab := ((id,impl,keep)::vars,repl,abs)::sl let rec extract_hyps = function - | (id::idl,(id',_,_ as d)::hyps) when id=id' -> d :: extract_hyps (idl,hyps) + | ((id,impl,keep)::idl,(id',_,_ as d)::hyps) when id=id' -> d :: extract_hyps (idl,hyps) + | ((id,impl,Some ty)::idl,hyps) -> (id,None,ty) :: extract_hyps (idl,hyps) | (id::idl,hyps) -> extract_hyps (idl,hyps) | [], _ -> [] @@ -429,6 +474,8 @@ let add_section_constant kn = let replacement_context () = pi2 (List.hd !sectab) +let variables_context () = pi1 (List.hd !sectab) + let section_segment_of_constant con = Cmap.find con (fst (pi3 (List.hd !sectab))) @@ -442,15 +489,15 @@ let section_instance = function | IndRef (kn,_) | ConstructRef ((kn,_),_) -> KNmap.find kn (snd (pi2 (List.hd !sectab))) -let init () = sectab := [] -let freeze () = !sectab -let unfreeze s = sectab := s +let init_sectab () = sectab := [] +let freeze_sectab () = !sectab +let unfreeze_sectab s = sectab := s let _ = Summary.declare_summary "section-context" - { Summary.freeze_function = freeze; - Summary.unfreeze_function = unfreeze; - Summary.init_function = init; + { Summary.freeze_function = freeze_sectab; + Summary.unfreeze_function = unfreeze_sectab; + Summary.init_function = init_sectab; Summary.survive_module = false; Summary.survive_section = false } @@ -476,7 +523,7 @@ let open_section id = (*Pushed for the lifetime of the section: removed by unfrozing the summary*) Nametab.push_dir (Nametab.Until 1) dir (DirOpenSection prefix); path_prefix := prefix; - if !Options.xml_export then !xml_open_section id; + if !Flags.xml_export then !xml_open_section id; add_section () @@ -486,9 +533,9 @@ let open_section id = let discharge_item ((sp,_ as oname),e) = match e with | Leaf lobj -> - option_map (fun o -> (basename sp,o)) (discharge_object (oname,lobj)) + Option.map (fun o -> (basename sp,o)) (discharge_object (oname,lobj)) | FrozenState _ -> None - | ClosedSection -> None + | ClosedSection _ | ClosedModtype _ | ClosedModule _ -> None | OpenedSection _ | OpenedModtype _ | OpenedModule _ | CompilingLibrary _ -> anomaly "discharge_item" @@ -504,21 +551,29 @@ let close_section id = with Not_found -> error "no opened section" in - let (secdecls,_,before) = split_lib oname in + let var_info = List.map + (fun (x, y, z) -> (x, y, match z with Some _ -> true | None -> false)) + (variables_context ()) + in + let (secdecls,secopening,before) = split_lib oname in lib_stk := before; let full_olddir = fst !path_prefix in pop_path_prefix (); - add_entry (make_oname id) ClosedSection; - if !Options.xml_export then !xml_close_section id; + add_entry (make_oname id) (ClosedSection (List.rev_append secdecls (List.rev secopening))); + if !Flags.xml_export then !xml_close_section id; let newdecls = List.map discharge_item secdecls in Summary.section_unfreeze_summaries fs; - List.iter (option_iter (fun (id,o) -> add_discharged_leaf id o)) newdecls; + List.iter (Option.iter (fun (id,o) -> add_discharged_leaf id var_info o)) newdecls; Cooking.clear_cooking_sharing (); Nametab.push_dir (Nametab.Until 1) full_olddir (DirClosedSection full_olddir) (*****************) (* Backtracking. *) +let (inLabel,outLabel) = + declare_object {(default_object "DOT") with + classify_function = (fun _ -> Dispose)} + let recache_decl = function | (sp, Leaf o) -> cache_object (sp,o) | (_,OpenedSection _) -> add_section () @@ -529,16 +584,58 @@ let recache_context ctx = let is_frozen_state = function (_,FrozenState _) -> true | _ -> false -let reset_to sp = - let (_,_,before) = split_lib sp in - lib_stk := before; +let has_top_frozen_state () = + let rec aux = function + | (sp, FrozenState _)::_ -> Some sp + | (sp, Leaf o)::t when object_tag o = "DOT" -> aux t + | _ -> None + in aux !lib_stk + +let set_lib_stk new_lib_stk = + lib_stk := new_lib_stk; recalc_path_prefix (); let spf = match find_entry_p is_frozen_state with | (sp, FrozenState f) -> unfreeze_summaries f; sp | _ -> assert false in let (after,_,_) = split_lib spf in - recache_context after + try + recache_context after + with + | Not_found -> error "Tried to set environment to an incoherent state." + +let reset_to_gen test = + let (_,_,before) = split_lib_gen test in + set_lib_stk before + +let reset_to sp = reset_to_gen (fun x -> (fst x) = sp) + +let reset_to_state sp = + let (_,eq,before) = split_lib sp in + (* if eq a frozen state, we'll reset to it *) + match eq with + | [_,FrozenState f] -> lib_stk := eq@before; unfreeze_summaries f + | _ -> error "Not a frozen state" + + +(* LEM: TODO + * We will need to muck with frozen states in after, too! + * Not only FrozenState, but also those embedded in Opened(Section|Module|Modtype) + *) +let delete_gen test = + let (after,equal,before) = split_lib_gen test in + let rec chop_at_dot = function + | [] as l -> l + | (_, Leaf o)::t when object_tag o = "DOT" -> t + | _::t -> chop_at_dot t + and chop_before_dot = function + | [] as l -> l + | (_, Leaf o)::t as l when object_tag o = "DOT" -> l + | _::t -> chop_before_dot t + in + set_lib_stk (List.rev_append (chop_at_dot after) (chop_before_dot before)) + +let delete sp = delete_gen (fun x -> (fst x) = sp) let reset_name (loc,id) = let (sp,_) = @@ -549,10 +646,20 @@ let reset_name (loc,id) = in reset_to sp +let remove_name (loc,id) = + let (sp,_) = + try + find_entry_p (fun (sp,_) -> let (_,spi) = repr_path (fst sp) in id = spi) + with Not_found -> + user_err_loc (loc,"remove_name",pr_id id ++ str ": no such entry") + in + delete sp + let is_mod_node = function | OpenedModule _ | OpenedModtype _ | OpenedSection _ - | ClosedSection -> true - | Leaf o -> let t = object_tag o in t = "MODULE" || t = "MODULE TYPE" + | ClosedModule _ | ClosedModtype _ | ClosedSection _ -> true + | Leaf o -> let t = object_tag o in t = "MODULE" || t = "MODULE TYPE" + || t = "MODULE ALIAS" | _ -> false (* Reset on a module or section name in order to bypass constants with @@ -567,19 +674,7 @@ let reset_mod (loc,id) = with Not_found -> user_err_loc (loc,"reset_mod",pr_id id ++ str ": no such entry") in - lib_stk := before; - recalc_path_prefix (); - let spf = match find_entry_p is_frozen_state with - | (sp, FrozenState f) -> unfreeze_summaries f; sp - | _ -> assert false - in - let (after,_,_) = split_lib spf in - recache_context after - - -let (inLabel,outLabel) = - declare_object {(default_object "DOT") with - classify_function = (fun _ -> Dispose)} + set_lib_stk before let mark_end_of_command, current_command_label, set_command_label = let n = ref 0 in @@ -590,17 +685,23 @@ let mark_end_of_command, current_command_label, set_command_label = (fun () -> !n), (fun x -> n:=x) -let rec reset_label_stk n stk = - match stk with - (sp,Leaf o)::tail when object_tag o = "DOT" && n = outLabel o -> sp - | _::tail -> reset_label_stk n tail - | [] -> error "Unknown state number" +let is_label_n n x = + match x with + | (sp,Leaf o) when object_tag o = "DOT" && n = outLabel o -> true + | _ -> false +(* Reset the label registered by [mark_end_of_command()] with number n. *) let reset_label n = - let res = reset_label_stk n !lib_stk in - set_command_label (n-1); (* forget state numbers after n only if reset succeeded *) - reset_to res - + let current = current_command_label() in + if n < current then + let res = reset_to_gen (is_label_n n) in + set_command_label (n-1); (* forget state numbers after n only if reset succeeded *) + res + else (* optimisation to avoid recaching when not necessary (why is it so long??) *) + match !lib_stk with + | [] -> () + | x :: ls -> (lib_stk := ls;set_command_label (n-1)) + let rec back_stk n stk = match stk with (sp,Leaf o)::tail when object_tag o = "DOT" -> @@ -688,6 +789,14 @@ let remove_section_part ref = (************************) (* Discharging names *) +let pop_kn kn = + let (mp,dir,l) = Names.repr_kn kn in + Names.make_kn mp (dirpath_prefix dir) l + +let pop_con con = + let (mp,dir,l) = Names.repr_con con in + Names.make_con mp (dirpath_prefix dir) l + let con_defined_in_sec kn = let _,dir,_ = repr_con kn in dir <> empty_dirpath && fst (split_dirpath dir) = snd (current_prefix ()) |