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 explicit: bool (* need explicit context root? *)
34 type resolver = Local of int
37 let hsize = 7000 (* hash tables initial size *)
39 (* Internal functions *******************************************************)
41 let initial_status size = {
42 path = []; node = None; nodes = []; line = 1; explicit = true;
43 henv = H.create size; hcnt = H.create size
46 let id_of_name (id, _, _) = id
49 let str = String.concat "/" path in
50 let str = Filename.concat str id in
51 U.uri_of_string ("ld:/" ^ str), id, path
53 let uri_of_qid (uri, _, _) = uri
55 let complete_qid f st (id, is_local, qs) =
56 let f qs = f (mk_qid id qs) in
57 let f path = Cps.list_rev_append f path ~tail:qs in
58 let rec skip f = function
59 | phd :: ptl, qshd :: _ when phd = qshd -> f ptl
60 | _ :: ptl, _ :: _ -> skip f (ptl, qs)
63 if is_local then f st.path else skip f (st.path, qs)
65 let relax_qid f (_, id, path) =
66 let f path = f (mk_qid id path) in
68 | _ :: tl -> Cps.list_rev f tl
73 let relax_opt_qid f = function
75 | Some qid -> let f qid = f (Some qid) in relax_qid f qid
77 let resolve_lref f st l lenv id =
78 let rec aux f i = function
80 | (name, _) :: _ when name = id -> f (Some (M.LRef (l, i)))
81 | _ :: tl -> aux f (succ i) tl
85 let resolve_lref_strict f st l lenv id =
88 | None -> assert false
90 resolve_lref f st l lenv id
92 let resolve_gref f st qid =
93 try let args = H.find st.henv (uri_of_qid qid) in f qid (Some args)
94 with Not_found -> f qid None
96 let resolve_gref_relaxed f st qid =
97 let rec g qid = function
98 | None -> relax_qid (resolve_gref g st) qid
99 | Some args -> f qid args
101 resolve_gref g st qid
103 let get_pars f st = function
105 | Some qid as node ->
106 try let pars = H.find st.hcnt (uri_of_qid qid) in f pars None
107 with Not_found -> f [] (Some node)
109 let get_pars_relaxed f st =
110 let rec g pars = function
112 | Some node -> relax_opt_qid (get_pars g st) node
114 get_pars g st st.node
116 let rec xlate_term f st lenv = function
120 let f vv tt = f (M.Appl (vv, tt)) in
121 let f vv = xlate_term (f vv) st lenv t in
122 xlate_term f st lenv v
123 | A.Abst (name, w, t) ->
124 let add name w lenv = (name, w) :: lenv in
125 let f ww tt = f (M.Abst (name, ww, tt)) in
126 let f ww = xlate_term (f ww) st (add name ww lenv) t in
127 xlate_term f st lenv w
128 | A.GRef (name, args) ->
129 let l = List.length lenv in
131 let map1 f = xlate_term f st lenv in
132 let map2 f (id, _) = resolve_lref_strict f st l lenv id in
134 let f args = f (M.GRef (l, uri_of_qid qid, args)) in
135 let f defs = Cps.list_rev_map_append f map2 defs ~tail in
136 Cps.list_sub_strict f defs args
138 Cps.list_map f map1 args
140 let g qid = resolve_gref_relaxed g st qid in
143 | None -> complete_qid g st name
145 resolve_lref f st l lenv (id_of_name name)
147 let xlate_item f st = function
148 | A.Section (Some name) ->
149 f {st with path = name :: st.path; nodes = st.node :: st.nodes} None
151 begin match st.path, st.nodes with
152 | _ :: ptl, nhd :: ntl ->
153 f {st with path = ptl; node = nhd; nodes = ntl} None
157 f {st with node = None} None
158 | A.Context (Some name) ->
159 let f name = f {st with node = Some name} None in
160 complete_qid f st name
161 | A.Block (name, w) ->
165 H.add st.hcnt (uri_of_qid qid) ((name, ww) :: pars);
166 f {st with node = Some qid} None
168 xlate_term f st pars w
170 get_pars_relaxed f st
172 complete_qid f st (name, true, [])
173 | A.Decl (name, w) ->
177 let entry = (st.line, pars, uri_of_qid qid, ww, None) in
178 H.add st.henv (uri_of_qid qid) pars;
179 f {st with line = succ st.line} (Some entry)
181 xlate_term f st pars w
183 complete_qid f st (name, true, [])
185 get_pars_relaxed f st
186 | A.Def (name, w, trans, v) ->
190 let entry = (st.line, pars, uri_of_qid qid, ww, Some (trans, vv)) in
191 H.add st.henv (uri_of_qid qid) pars;
192 f {st with line = succ st.line} (Some entry)
194 let f ww = xlate_term (f ww) st pars v in
195 xlate_term f st pars w
197 complete_qid f st (name, true, [])
199 get_pars_relaxed f st
201 (* Interface functions ******************************************************)
203 let initial_status = initial_status hsize
205 let meta_of_aut = xlate_item