1 (* path indexing implementation *)
3 (* position of the subterm, subterm (Appl are not stored...) *)
4 type path_string_elem = Index of int | Term of Cic.term;;
5 type path_string = path_string_elem list;;
8 let rec path_strings_of_term index =
9 let module C = Cic in function
10 | C.Meta _ -> [ [Index index; Term (C.Implicit None)] ]
12 let p = if index > 0 then [Index index; Term hd] else [Term hd] in
16 let rr = path_strings_of_term i t in
17 (i+1, r @ (List.map (fun ps -> p @ ps) rr)))
21 | term -> [ [Index index; Term term] ]
25 let string_of_path_string ps =
31 | Index i -> "Index " ^ (string_of_int i)
32 | Term t -> "Term " ^ (CicPp.ppterm t)
39 module OrderedPathStringElement = struct
40 type t = path_string_elem
44 | Index i, Index j -> Pervasives.compare i j
45 | Term t1, Term t2 -> if t1 = t2 then 0 else Pervasives.compare t1 t2
46 | Index _, Term _ -> -1
47 | Term _, Index _ -> 1
50 module PSMap = Map.Make(OrderedPathStringElement);;
52 module OrderedPosEquality = struct
53 type t = Utils.pos * Inference.equality
55 let compare = Pervasives.compare
58 module PosEqSet = Set.Make(OrderedPosEquality);;
60 module PSTrie = Trie.Make(PSMap);;
64 * Trie: maps over lists.
65 * Copyright (C) 2000 Jean-Christophe FILLIATRE
67 module PSTrie = struct
68 type key = path_string
69 type t = Node of PosEqSet.t option * (t PSMap.t)
71 let empty = Node (None, PSMap.empty)
75 | [], Node (None, _) -> raise Not_found
76 | [], Node (Some v, _) -> v
77 | x::r, Node (_, m) -> find r (PSMap.find x m)
81 | [], Node (None, _) -> false
82 | [], Node (Some _, _) -> true
83 | x::r, Node (_, m) -> try mem r (PSMap.find x m) with Not_found -> false
86 let rec ins = function
87 | [], Node (_, m) -> Node (Some v, m)
88 | x::r, Node (v, m) ->
89 let t' = try PSMap.find x m with Not_found -> empty in
90 let t'' = ins (r, t') in
91 Node (v, PSMap.add x t'' m)
97 | [], Node (_, m) -> Node (None, m)
98 | x::r, Node (v, m) ->
100 let t' = remove r (PSMap.find x m) in
101 Node (v, if t' = empty then PSMap.remove x m else PSMap.add x t' m)
105 let rec fold f t acc =
106 let rec traverse revp t acc = match t with
108 PSMap.fold (fun x -> traverse (x::revp)) m acc
109 | Node (Some v, m) ->
110 f (List.rev revp) v (PSMap.fold (fun x -> traverse (x::revp)) m acc)
118 let index trie equality =
119 let _, (_, l, r, ordering), _, _ = equality in
120 let psl = path_strings_of_term 0 l
121 and psr = path_strings_of_term 0 r in
122 let index pos trie ps =
123 let ps_set = try PSTrie.find ps trie with Not_found -> PosEqSet.empty in
124 let trie = PSTrie.add ps (PosEqSet.add (pos, equality) ps_set) trie in
125 (* if PosEqSet.mem (pos, equality) (PSTrie.find ps trie) then *)
126 (* Printf.printf "OK: %s, %s indexed\n" (Utils.string_of_pos pos) *)
127 (* (Inference.string_of_equality equality); *)
131 | Utils.Gt -> List.fold_left (index Utils.Left) trie psl
132 | Utils.Lt -> List.fold_left (index Utils.Right) trie psr
134 let trie = List.fold_left (index Utils.Left) trie psl in
135 List.fold_left (index Utils.Right) trie psr
139 let remove_index trie equality =
140 let _, (_, l, r, ordering), _, _ = equality in
141 let psl = path_strings_of_term 0 l
142 and psr = path_strings_of_term 0 r in
143 let remove_index pos trie ps =
145 let ps_set = PosEqSet.remove (pos, equality) (PSTrie.find ps trie) in
146 if PosEqSet.is_empty ps_set then
147 PSTrie.remove ps trie
149 PSTrie.add ps ps_set trie
151 (* Printf.printf "NOT_FOUND: %s, %s\n" (Utils.string_of_pos pos) *)
152 (* (Inference.string_of_equality equality); *)
154 (* raise Not_found *)
157 | Utils.Gt -> List.fold_left (remove_index Utils.Left) trie psl
158 | Utils.Lt -> List.fold_left (remove_index Utils.Right) trie psr
160 let trie = List.fold_left (remove_index Utils.Left) trie psl in
161 List.fold_left (remove_index Utils.Right) trie psr
165 let in_index trie equality =
166 let _, (_, l, r, ordering), _, _ = equality in
167 let psl = path_strings_of_term 0 l
168 and psr = path_strings_of_term 0 r in
169 let meta_convertibility = Inference.meta_convertibility_eq equality in
172 let set = PSTrie.find ps trie in
173 PosEqSet.exists (fun (p, e) -> meta_convertibility e) set
177 (List.exists ok psl) || (List.exists ok psr)
181 let head_of_term = function
182 | Cic.Appl (hd::tl) -> hd
187 let subterm_at_pos index term =
193 (try List.nth l index with Failure _ -> raise Not_found)
194 | _ -> raise Not_found
198 let rec retrieve_generalizations trie term =
200 | PSTrie.Node (value, map) ->
203 | Cic.Meta _ -> PosEqSet.empty
205 let hd_term = head_of_term term in
207 let n = PSMap.find (Term hd_term) map in
209 | PSTrie.Node (Some s, _) -> s
210 | PSTrie.Node (None, m) ->
216 let t = subterm_at_pos i term in
217 let s = retrieve_generalizations v t in
224 List.fold_left (fun r s -> PosEqSet.inter r s) hd tl
225 | _ -> PosEqSet.empty
230 let n = PSMap.find (Term (Cic.Implicit None)) map in
232 | PSTrie.Node (Some s, _) -> PosEqSet.union res s
239 let rec retrieve_unifiables trie term =
241 | PSTrie.Node (value, map) ->
246 (fun ps v res -> PosEqSet.union res v)
247 (PSTrie.Node (None, map))
250 let hd_term = head_of_term term in
252 let n = PSMap.find (Term hd_term) map in
254 | PSTrie.Node (Some v, _) -> v
255 | PSTrie.Node (None, m) ->
261 let t = subterm_at_pos i term in
262 let s = retrieve_unifiables v t in
269 List.fold_left (fun r s -> PosEqSet.inter r s) hd tl
270 | _ -> PosEqSet.empty
272 (* Printf.printf "Not_found: %s, term was: %s\n" *)
273 (* (CicPp.ppterm hd_term) (CicPp.ppterm term); *)
274 (* Printf.printf "map is:\n %s\n\n" *)
275 (* (String.concat "\n" *)
279 (* | Index i -> ("Index " ^ (string_of_int i))::l *)
280 (* | Term t -> ("Term " ^ (CicPp.ppterm t))::l) *)
285 let n = PSMap.find (Term (Cic.Implicit None)) map in
287 | PSTrie.Node (Some s, _) -> PosEqSet.union res s
294 let string_of_pstrie trie =
295 let rec to_string level = function
296 | PSTrie.Node (v, map) ->
300 (String.make (2 * level) ' ') ^
301 "{" ^ (String.concat "; "
304 "(" ^ (Utils.string_of_pos p) ^ ", " ^
305 (Inference.string_of_equality e) ^ ")")
306 (PosEqSet.elements v))) ^ "}"
315 | Index i -> "Index " ^ (string_of_int i)
316 | Term t -> "Term " ^ (CicPp.ppterm t)
318 let rs = to_string (level+1) v in
319 ((String.make (2 * level) ' ') ^ ks ^ "\n" ^ rs)::s)