2 ||M|| This file is part of HELM, an Hypertextual, Electronic
3 ||A|| Library of Mathematics, developed at the Computer Science
4 ||T|| Department, University of Bologna, Italy.
6 ||T|| HELM is free software; you can redistribute it and/or
7 ||A|| modify it under the terms of the GNU General Public License
8 \ / version 2 or (at your option) any later version.
9 \ / This software is distributed as is, NO WARRANTY.
10 V_______________________________________________________________ *)
17 (* qualified identifier: uri, name, qualifiers *)
18 type qid = U.uri * M.id * M.id list
20 type environment = M.pars H.t
22 type context_node = qid option (* context node: None = root *)
25 henv: environment; (* optimized global environment *)
26 path: M.id list; (* current section path *)
27 hcnt: environment; (* optimized context *)
28 node: context_node; (* current context node *)
29 nodes: context_node list; (* context node list *)
30 line: int; (* line number *)
31 cover: string (* initial segment of URI hierarchy *)
34 type resolver = Local of int
37 let hsize = 7000 (* hash tables initial size *)
39 (* Internal functions *******************************************************)
41 let initial_status size cover = {
42 path = []; node = None; nodes = []; line = 1; cover = cover;
43 henv = H.create size; hcnt = H.create size
46 let id_of_name (id, _, _) = id
48 let mk_qid st id path =
49 let uripath = if st.cover = "" then path else st.cover :: path in
50 let str = String.concat "/" uripath in
51 let str = Filename.concat str id in
52 U.uri_of_string ("ld:/" ^ str), id, path
54 let uri_of_qid (uri, _, _) = uri
56 let complete_qid f st (id, is_local, qs) =
57 let f qs = f (mk_qid st id qs) in
58 let f path = Cps.list_rev_append f path ~tail:qs in
59 let rec skip f = function
60 | phd :: ptl, qshd :: _ when phd = qshd -> f ptl
61 | _ :: ptl, _ :: _ -> skip f (ptl, qs)
64 if is_local then f st.path else skip f (st.path, qs)
66 let relax_qid f st (_, id, path) =
67 let f path = f (mk_qid st id path) in
69 | _ :: tl -> Cps.list_rev f tl
74 let relax_opt_qid f st = function
76 | Some qid -> let f qid = f (Some qid) in relax_qid f st qid
78 let resolve_lref f st l lenv id =
79 let rec aux f i = function
81 | (name, _) :: _ when name = id -> f (Some (M.LRef (l, i)))
82 | _ :: tl -> aux f (succ i) tl
86 let resolve_lref_strict f st l lenv id =
89 | None -> assert false
91 resolve_lref f st l lenv id
93 let resolve_gref f st qid =
94 try let args = H.find st.henv (uri_of_qid qid) in f qid (Some args)
95 with Not_found -> f qid None
97 let resolve_gref_relaxed f st qid =
98 let rec g qid = function
99 | None -> relax_qid (resolve_gref g st) st qid
100 | Some args -> f qid args
102 resolve_gref g st qid
104 let get_pars f st = function
106 | Some qid as node ->
107 try let pars = H.find st.hcnt (uri_of_qid qid) in f pars None
108 with Not_found -> f [] (Some node)
110 let get_pars_relaxed f st =
111 let rec g pars = function
113 | Some node -> relax_opt_qid (get_pars g st) st node
115 get_pars g st st.node
117 let rec xlate_term f st lenv = function
121 let f vv tt = f (M.Appl (vv, tt)) in
122 let f vv = xlate_term (f vv) st lenv t in
123 xlate_term f st lenv v
124 | A.Abst (name, w, t) ->
125 let add name w lenv = (name, w) :: lenv in
126 let f ww tt = f (M.Abst (name, ww, tt)) in
127 let f ww = xlate_term (f ww) st (add name ww lenv) t in
128 xlate_term f st lenv w
129 | A.GRef (name, args) ->
130 let l = List.length lenv in
132 let map1 f = xlate_term f st lenv in
133 let map2 f (id, _) = resolve_lref_strict f st l lenv id in
135 let f args = f (M.GRef (l, uri_of_qid qid, args)) in
136 let f defs = Cps.list_rev_map_append f map2 defs ~tail in
137 Cps.list_sub_strict f defs args
139 Cps.list_map f map1 args
141 let g qid = resolve_gref_relaxed g st qid in
144 | None -> complete_qid g st name
146 resolve_lref f st l lenv (id_of_name name)
148 let xlate_item f st = function
149 | A.Section (Some (_, name)) ->
150 f {st with path = name :: st.path; nodes = st.node :: st.nodes} None
152 begin match st.path, st.nodes with
153 | _ :: ptl, nhd :: ntl ->
154 f {st with path = ptl; node = nhd; nodes = ntl} None
158 f {st with node = None} None
159 | A.Context (Some name) ->
160 let f name = f {st with node = Some name} None in
161 complete_qid f st name
162 | A.Block (name, w) ->
166 H.add st.hcnt (uri_of_qid qid) ((name, ww) :: pars);
167 f {st with node = Some qid} None
169 xlate_term f st pars w
171 get_pars_relaxed f st
173 complete_qid f st (name, true, [])
174 | A.Decl (name, w) ->
178 let entry = (st.line, pars, uri_of_qid qid, ww, None) in
179 H.add st.henv (uri_of_qid qid) pars;
180 f {st with line = succ st.line} (Some entry)
182 xlate_term f st pars w
184 complete_qid f st (name, true, [])
186 get_pars_relaxed f st
187 | A.Def (name, w, trans, v) ->
191 let entry = (st.line, pars, uri_of_qid qid, ww, Some (trans, vv)) in
192 H.add st.henv (uri_of_qid qid) pars;
193 f {st with line = succ st.line} (Some entry)
195 let f ww = xlate_term (f ww) st pars v in
196 xlate_term f st pars w
198 complete_qid f st (name, true, [])
200 get_pars_relaxed f st
202 (* Interface functions ******************************************************)
204 let initial_status ?(cover="") () =
205 initial_status hsize cover
207 let meta_of_aut = xlate_item