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_______________________________________________________________ *)
16 module E = BrgEnvironment
18 exception LRefNotFound of string Lazy.t
24 type environment = int * bind list
26 type stack = B.term list
36 | LRef_ of int * B.term option
37 | GRef_ of int * B.bind * B.term
38 | Bind_ of B.term * B.term
44 (* Internal functions *******************************************************)
48 let push_e f b (l, e) =
52 let (gl, ge), (ll, le) = c.g, c.l in
53 if i >= gl + ll then raise (LRefNotFound (lazy (string_of_int i)));
55 if i < gl then List.nth ge (gl - (succ i))
56 else List.nth le (gl + ll - (succ i))
60 let rec lref_map f map t = match t with
61 | B.LRef i -> f (B.LRef (map i))
65 let f w' u' = f (S.sh2 w w' u u' t B.cast) in
66 let f w' = lref_map (f w') map u in
69 let f w' u' = f (S.sh2 w w' u u' t B.appl) in
70 let f w' = lref_map (f w') map u in
72 | B.Bind (id, b, w, u) ->
73 let f w' u' = f (S.sh2 w w' u u' t (B.bind id b)) in
74 let f w' = lref_map (f w') map u in
79 let (gl, _), (ll, le) = c.g, c.l in
80 let map i = if i >= gl then succ i else i in
82 | Abbr_ t -> let f t' = f (Abbr_ t') in lref_map f map t
85 let f le' = f {c with l = (ll, le')} in
89 let (gl, _), (ll, _) = c.g, c.l in
91 if i < gl || i > gl + ll then i else
92 if i >= gl && i < gl + ll then succ i else gl
97 let rec whd f c t = match t with
98 | B.Sort h -> f c (Sort_ h)
100 let f (i, _, b, t) = f c (GRef_ (i, b, t)) in
104 | Void_ -> f c (LRef_ (i, None))
105 | Abst_ t -> f c (LRef_ (i, Some t))
106 | Abbr_ t -> whd f c t
109 | B.Appl (v, t) -> whd f {c with s = v :: c.s} t
110 | B.Bind (_, B.Abbr, v, t) ->
111 let f l = whd f {c with l = l} t in
112 push_e f (Abbr_ v) c.l
113 | B.Bind (_, B.Abst, w, t) ->
115 | [] -> f c (Bind_ (w, t))
117 let f tl l = whd f {c with l = l; s = tl} t in
118 push_e (f tl) (Abbr_ v) c.l
120 | B.Cast (_, t) -> whd f c t
124 let f c g = xchg f {c with g = g} t in
125 let f c = push_e (f c) Void_ c.g in
128 (* Interface functions ******************************************************)
130 let rec are_convertible f c1 t1 c2 t2 =
131 let rec aux c1' r1 c2' r2 = match r1, r2 with
132 | Sort_ h1, Sort_ h2 -> f (h1 = h2)
133 | LRef_ (i1, _), LRef_ (i2, _) ->
134 if i1 = i2 then are_convertible_stacks f c1' c2' else f false
135 | GRef_ (a1, B.Abst, _), GRef_ (a2, B.Abst, _) ->
136 if a1 = a2 then are_convertible_stacks f c1' c2' else f false
137 | GRef_ (a1, B.Abbr, v1), GRef_ (a2, B.Abbr, v2) ->
138 if a1 = a2 then are_convertible_stacks f c1' c2' else
139 if a1 < a2 then whd (aux c1' r1) c2' v2 else
140 whd (aux_rev c2' r2) c1' v1
141 | _, GRef_ (_, B.Abbr, v2) ->
142 whd (aux c1' r1) c2' v2
143 | GRef_ (_, B.Abbr, v1), _ ->
144 whd (aux_rev c2' r2) c1' v1
145 | Bind_ (w1, t1), Bind_ (w2, t2) ->
148 let f c1'' t1' = push (are_convertible f c1'' t1') c2' t2 in
152 are_convertible f c1' w1 c2' w2
154 and aux_rev c2 r2 c1 r1 = aux c1 r1 c2 r2 in
155 let f c1' r1 = whd (aux c1' r1) c2 t2 in
158 and are_convertible_stacks f c1 c2 =
159 let map f v1 v2 = are_convertible f c1 v1 c2 v2 in
160 if List.length c1.s <> List.length c2.s then f false else
161 C.forall2 f map c1.s c2.s
163 let are_convertible f c t1 t2 = are_convertible f c t1 c t2
165 let rec ho_whd f c t =
166 let aux c' = function
167 | Sort_ h -> f c' (Sort h)
168 | Bind_ (w, t) -> f c' (Abst w)
169 | LRef_ (_, Some w) -> ho_whd f c w
170 | GRef_ (_, _, u) -> ho_whd f c u
171 | LRef_ (_, None) -> assert false
176 assert (c.l = empty_e && c.s = []);
177 let f g = f {c with g = g} in
186 if i >= gl then raise (LRefNotFound (lazy (string_of_int i)));
187 match List.nth ge (gl - (succ i)) with
188 | Abbr_ v -> f (B.Abbr, v)
189 | Abst_ w -> f (B.Abst, w)
190 | Void_ -> assert false
192 let empty_context = {
193 g = empty_e; l = empty_e; s = []