]> matita.cs.unibo.it Git - helm.git/blob - helm/software/lambda-delta/src/complete_rg/crgAut.ml
2221c3c06a88ff4b925f2d0ac9b43c8dd41d6c92
[helm.git] / helm / software / lambda-delta / src / complete_rg / crgAut.ml
1 (*
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.                     
5     ||I||                                                                
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_______________________________________________________________ *)
11
12 module U = NUri
13 module K = U.UriHash
14 module C = Cps
15 module G = Options
16 module E = Entity
17 module A = Aut
18 module D = Crg
19
20 (* qualified identifier: uri, name, qualifiers *)
21 type qid = D.uri * D.id * D.id list
22
23 type context = E.attrs * D.term list
24
25 type context_node = qid option (* context node: None = root *)
26
27 type status = {
28    path: D.id list;          (* current section path *) 
29    node: context_node;       (* current context node *)
30    nodes: context_node list; (* context node list *)
31    line: int;                (* line number *)
32    mk_uri:G.uri_generator    (* uri generator *) 
33 }
34
35 type resolver = Local of int
36               | Global of context
37
38 let henv_size, hcnt_size = 7000, 4300 (* hash tables initial sizes *)
39
40 let henv = K.create henv_size (* optimized global environment *)
41
42 let hcnt = K.create hcnt_size (* optimized context *)
43
44 (* Internal functions *******************************************************)
45
46 let empty_cnt = [], []
47
48 let add_abst (a, ws) id w = 
49    E.Name (id, true) :: a, w :: ws 
50
51 let lenv_of_cnt (a, ws) = 
52    D.push_bind C.start D.empty_lenv a (D.Abst ws)
53
54 let mk_lref f i j k = f (D.TLRef ([E.Apix k], i, j))
55
56 let id_of_name (id, _, _) = id
57
58 let mk_qid f st id path =
59    let str = String.concat "/" path in
60    let str = Filename.concat str id in 
61    let str = st.mk_uri str in
62    f (U.uri_of_string str, id, path)
63
64 let uri_of_qid (uri, _, _) = uri
65
66 let complete_qid f st (id, is_local, qs) =
67    let f path = C.list_rev_append (mk_qid f st id) path ~tail:qs in
68    let rec skip f = function
69       | phd :: ptl, qshd :: _ when phd = qshd -> f ptl
70       | _ :: ptl, _ :: _                      -> skip f (ptl, qs)
71       | _                                     -> f []
72    in
73    if is_local then f st.path else skip f (st.path, qs)
74
75 let relax_qid f st (_, id, path) =
76    let f = function
77       | _ :: tl -> C.list_rev (mk_qid f st id) tl
78       | []      -> assert false
79    in
80    C.list_rev f path
81
82 let relax_opt_qid f st = function
83    | None     -> f None
84    | Some qid -> let f qid = f (Some qid) in relax_qid f st qid
85
86 let resolve_gref err f st qid =
87    try let cnt = K.find henv (uri_of_qid qid) in f qid cnt
88    with Not_found -> err qid 
89
90 let resolve_gref_relaxed f st qid =
91 (* this is not tail recursive *)   
92    let rec err qid = relax_qid (resolve_gref err f st) st qid in
93    resolve_gref err f st qid
94
95 let get_cnt err f st = function
96    | None              -> f empty_cnt
97    | Some qid as node ->
98       try let cnt = K.find hcnt (uri_of_qid qid) in f cnt
99       with Not_found -> err node
100
101 let get_cnt_relaxed f st =
102 (* this is not tail recursive *)   
103    let rec err node = relax_opt_qid (get_cnt err f st) st node in
104    get_cnt err f st st.node
105
106 (* this is not tail recursive in the GRef branch *)
107 let rec xlate_term f st lenv = function
108    | A.Sort s            -> 
109       let f h = f (D.TSort ([], h)) in
110       if s then f 0 else f 1
111    | A.Appl (v, t)       ->
112       let f vv tt = f (D.TAppl ([], [vv], tt)) in
113       let f vv = xlate_term (f vv) st lenv t in
114       xlate_term f st lenv v
115    | A.Abst (name, w, t) ->
116       let f ww = 
117          let a, b = [E.Name (name, true)], (D.Abst [ww]) in
118          let f tt = f (D.TBind (a, b, tt)) in
119          let f lenv = xlate_term f st lenv t in
120          D.push_bind f lenv a b
121       in
122       xlate_term f st lenv w
123    | A.GRef (name, args) ->
124       let map1 f = function
125             | E.Name (id, _) -> f (A.GRef ((id, true, []), []))
126             | _              -> C.err ()
127       in
128       let map2 f = xlate_term f st lenv in
129       let g qid (a, _) =
130          let gref = D.TGRef ([], uri_of_qid qid) in
131          match args, a with
132             | [], [] -> f gref
133             | _      -> 
134                let f args = f (D.TAppl ([], args, gref)) in
135                let f args = f (List.rev_map (map2 C.start) args) in
136                let f a = C.list_rev_map_append f map1 a ~tail:args in
137                C.list_sub_strict f a args
138       in
139       let g qid = resolve_gref_relaxed g st qid in
140       let err () = complete_qid g st name in
141       D.resolve_lref err (mk_lref f) (id_of_name name) lenv
142
143 let xlate_entity err f st = function
144    | A.Section (Some (_, name))     ->
145       err {st with path = name :: st.path; nodes = st.node :: st.nodes}
146    | A.Section None            ->
147       begin match st.path, st.nodes with
148          | _ :: ptl, nhd :: ntl -> 
149             err {st with path = ptl; node = nhd; nodes = ntl}
150          | _                    -> assert false
151       end
152    | A.Context None            ->
153       err {st with node = None}
154    | A.Context (Some name)     ->
155       let f name = err {st with node = Some name} in
156       complete_qid f st name 
157    | A.Block (name, w)         ->
158       let f qid = 
159          let f cnt =
160             let lenv = lenv_of_cnt cnt in
161             let ww = xlate_term C.start st lenv w in
162             K.add hcnt (uri_of_qid qid) (add_abst cnt name ww);
163             err {st with node = Some qid}
164          in
165          get_cnt_relaxed f st
166       in
167       complete_qid f st (name, true, [])
168    | A.Decl (name, w)          ->
169       let f cnt =
170          let a, ws = cnt in
171          let lenv = lenv_of_cnt cnt in
172          let f qid = 
173             let ww = xlate_term C.start st lenv w in
174             K.add henv (uri_of_qid qid) cnt;
175             let t = match ws with
176                | [] -> ww
177                | _  -> D.TBind (a, D.Abst ws, ww)
178             in
179 (*
180             print_newline (); CrgOutput.pp_term print_string t;
181 *)
182             let b = E.Abst t in
183             let entity = [E.Mark st.line], uri_of_qid qid, b in
184             f {st with line = succ st.line} entity
185          in
186          complete_qid f st (name, true, [])
187       in
188       get_cnt_relaxed f st
189    | A.Def (name, w, trans, v) ->
190       let f cnt = 
191          let a, ws = cnt in
192          let lenv = lenv_of_cnt cnt in
193          let f qid = 
194             let ww = xlate_term C.start st lenv w in
195             let vv = xlate_term C.start st lenv v in
196             K.add henv (uri_of_qid qid) cnt;
197             let t = match ws with
198                | [] -> D.TCast ([], ww, vv)
199                | _  -> D.TBind (a, D.Abst ws, D.TCast ([], ww, vv))
200             in
201 (*
202             print_newline (); CrgOutput.pp_term print_string t;
203 *)
204             let b = E.Abbr t in
205             let a = E.Mark st.line :: if trans then [] else [E.Priv] in
206             let entity = a, uri_of_qid qid, b in
207             f {st with line = succ st.line} entity
208          in
209          complete_qid f st (name, true, [])
210       in
211       get_cnt_relaxed f st
212
213 (* Interface functions ******************************************************)
214
215 let initial_status () =
216    K.clear henv; K.clear hcnt; {
217    path = []; node = None; nodes = []; line = 1; mk_uri = G.get_mk_uri ()
218 }
219
220 let refresh_status st = {st with
221    mk_uri = G.get_mk_uri ()
222 }
223
224 let crg_of_aut = xlate_entity