]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/lambda-delta/basic_rg/brgReduction.ml
thanks to the new fixes to notation, I can define \land for both pairs and
[helm.git] / helm / software / lambda-delta / basic_rg / brgReduction.ml
index b194b00bf579e23709c28e5dc8b75ae91f404711..74f6a504887511303cec3fbe1aeb9163ead41bde 100644 (file)
       V_______________________________________________________________ *)
 
 module U = NUri
+module C = Cps
+module S = Share
+module L = Log
 module B = Brg
 module E = BrgEnvironment
 
-exception LRefNotFound of string Lazy.t
-
-type environment = int * (B.bind * B.term) list
+type environment = int * B.bind list
 
 type stack = B.term list
 
@@ -25,53 +26,176 @@ type context = {
    s: stack
 }
 
+exception LRefNotFound of (context, B.term) L.item list
+
 type whd_result =
    | Sort_ of int
-   | LRef_ of int 
-   | GRef_ of int * U.uri * B.bind 
-   | Abst_ of B.term
+   | LRef_ of int * B.term option
+   | GRef_ of int * B.bind
+   | Bind_ of B.term * B.term
+
+type ho_whd_result =
+   | Sort of int
+   | Abst of B.term
 
 (* Internal functions *******************************************************)
 
-let push_e f b t (l, e) =
-   f (succ l, (b, t) :: e)
+let error i = raise (LRefNotFound (L.items1 (string_of_int i)))
 
-let rec find_e f c i =
+let empty_e = 0, []
+
+let push_e f b (l, e) =
+   f (succ l, b :: e)
+
+let get_e f c i =
    let (gl, ge), (ll, le) = c.g, c.l in
-   if i >= gl + ll then raise (LRefNotFound (lazy (string_of_int i)));
-   let b, t =
+   if i >= gl + ll then error i;
+   let b =
       if i < gl then List.nth ge (gl - (succ i)) 
       else List.nth le (gl + ll - (succ i))
    in
-   f t b
-   
+   f b
+
+let rec lref_map_bind f map b = match b with
+   | B.Abbr v ->
+      let f v' = f (S.sh1 v v' b B.abbr) in
+      lref_map f map v      
+   | B.Abst w ->
+      let f w' = f (S.sh1 w w' b B.abst) in
+      lref_map f map w
+   | B.Void   -> f b
+
+and lref_map f map t = match t with
+   | B.LRef i          -> f (B.LRef (map i))
+   | B.GRef _          -> f t
+   | B.Sort _          -> f t
+   | B.Cast (w, u)     ->
+      let f w' u' = f (S.sh2 w w' u u' t B.cast) in
+      let f w' = lref_map (f w') map u in 
+      lref_map f map w
+   | B.Appl (w, u)     ->
+      let f w' u' = f (S.sh2 w w' u u' t B.appl) in
+      let f w' = lref_map (f w') map u in 
+      lref_map f map w
+   | B.Bind (id, b, u) ->
+      let f b' u' = f (S.sh2 b b' u u' t (B.bind id)) in
+      let f b' = lref_map (f b') map u in 
+      lref_map_bind f map b
+
+(* to share *)
+let lift f c = 
+   let (gl, _), (ll, le) = c.g, c.l in
+   let map i = if i >= gl then succ i else i in
+   let map f = function
+      | B.Abbr t -> let f t' = f (B.Abbr t') in lref_map f map t
+      | _       -> assert false
+   in
+   let f le' = f {c with l = (ll, le')} in
+   C.list_map f map le
+
+let xchg f c t =
+   let (gl, _), (ll, _) = c.g, c.l in
+   let map i =
+      if i < gl || i > gl + ll then i else
+      if i >= gl && i < gl + ll then succ i else gl
+   in
+   lref_map (f c) map t
+
+(* to share *)
 let rec whd f c t = match t with
-   | B.Sort h                 -> f c (Sort_ h)
+   | B.Sort h                 -> f c (Sort_ h)
    | B.GRef uri               ->
-      let f (i, _, b, t) = f c t (GRef_ (i, uri, b)) in
+      let f (i, _, b) = f c (GRef_ (i, b)) in
       E.get_obj f uri
-   | B.LRef i                 ->
-      let f t = function
-         | B.Abst -> f c t (LRef_ i)
-        | B.Abbr -> whd f c t
+   | B.LRef i                ->
+      let f = function
+         | B.Void   -> f c (LRef_ (i, None))
+        | B.Abst t -> f c (LRef_ (i, Some t))
+        | B.Abbr t -> whd f c t
       in
-      find_e f c i
-   | B.Appl (v, t)            -> whd f {c with s = v :: c.s} t   
-   | B.Bind (_, B.Abbr, v, t) -> 
-      let f l = whd f {c with l = l} t in
-      push_e f B.Abbr v c.l
-   | B.Bind (_, B.Abst, w, t) -> 
+      get_e f c i
+   | B.Cast (_, t)           -> whd f c t
+   | B.Appl (v, t)           -> whd f {c with s = v :: c.s} t   
+   | B.Bind (_, B.Abst w, t) -> 
       begin match c.s with
-         | []      -> f c t (Abst_ w)
+         | []      -> f c (Bind_ (w, t))
         | v :: tl -> 
            let f tl l = whd f {c with l = l; s = tl} t in
-           push_e (f tl) B.Abbr v c.l
+           push_e (f tl) (B.Abbr v) c.l
       end
-   | B.Cast (_, t)            -> whd f c t
+   | B.Bind (_, b, t) -> 
+      let f l = whd f {c with l = l} t in
+      push_e f b c.l
+
+let push f c t = 
+   assert (c.s = []);
+   let f c g = xchg f {c with g = g} t in
+   let f c = push_e (f c) B.Void c.g in
+   lift f c 
 
 (* Interface functions ******************************************************)
 
-let push f c b t = 
-   assert (fst c.l = 0 && c.s = []);
+let rec are_convertible f c1 t1 c2 t2 =
+   let rec aux c1' r1 c2' r2 = match r1, r2 with
+      | Sort_ h1, Sort_ h2                           -> f (h1 = h2)
+      | LRef_ (i1, _), LRef_ (i2, _)                 ->
+         if i1 = i2 then are_convertible_stacks f c1' c2' else f false
+      | GRef_ (a1, B.Abst _), GRef_ (a2, B.Abst _)   ->
+         if a1 = a2 then are_convertible_stacks f c1' c2' else f false
+      | GRef_ (a1, B.Abbr v1), GRef_ (a2, B.Abbr v2) ->
+         if a1 = a2 then are_convertible_stacks f c1' c2' else
+        if a1 < a2 then whd (aux c1' r1) c2' v2 else
+        whd (aux_rev c2' r2) c1' v1
+      | _, GRef_ (_, B.Abbr v2)                      ->
+         whd (aux c1' r1) c2' v2
+      | GRef_ (_, B.Abbr v1), _                      ->
+        whd (aux_rev c2' r2) c1' v1
+      | Bind_ (w1, t1), Bind_ (w2, t2)               ->
+         let f b = 
+           if b then 
+              let f c1'' t1' = push (are_convertible f c1'' t1') c2' t2 in
+               push f c1' t1
+           else f false
+        in
+        are_convertible f c1' w1 c2' w2
+      | _                                              -> f false
+   and aux_rev c2 r2 c1 r1 = aux c1 r1 c2 r2 in
+   let f c1' r1 = whd (aux c1' r1) c2 t2 in 
+   whd f c1 t1
+
+and are_convertible_stacks f c1 c2 =
+   let map f v1 v2 = are_convertible f c1 v1 c2 v2 in
+   if List.length c1.s <> List.length c2.s then f false else
+   C.forall2 f map c1.s c2.s
+
+let are_convertible f c t1 t2 = are_convertible f c t1 c t2
+
+let rec ho_whd f c t =
+   let aux c' = function
+      | Sort_ h             -> f c' (Sort h)
+      | Bind_ (w, t)        -> f c' (Abst w)
+      | LRef_ (_, Some w)   -> ho_whd f c w
+      | GRef_ (_, B.Abst u) -> ho_whd f c u
+      | GRef_ (_, B.Abbr u) -> ho_whd f c u
+      | LRef_ (_, None)     -> assert false
+      | GRef_ (_, B.Void)   -> assert false
+   in
+   whd aux c t
+
+let push f c b = 
+   assert (c.l = empty_e && c.s = []);
    let f g = f {c with g = g} in
-   push_e f b t c.g
+   push_e f b c.g
+
+let get f c i =
+   let gl, ge = c.g in
+   if i >= gl then error i;
+   f (List.nth ge (gl - (succ i)))
+
+let empty_context = {
+   g = empty_e; l = empty_e; s = []
+}
+
+let iter f map c =
+   let _, ge = c.g in   
+   C.list_iter f map ge