]> matita.cs.unibo.it Git - helm.git/blob - helm/software/lambda-delta/basic_ag/bagReduction.ml
0310e8d2833de378e435ae3ffcf80b998da5dcad
[helm.git] / helm / software / lambda-delta / basic_ag / bagReduction.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 C = Cps
13 module L = Log
14 module B = Bag
15 module O = BagOutput
16 module E = BagEnvironment
17 module S = BagSubstitution
18
19 exception LRefNotFound of B.message
20
21 type machine = {
22    c: B.context;
23    s: B.term list
24 }
25
26 type whd_result =
27    | Sort_ of int
28    | LRef_ of int * B.term option
29    | GRef_ of int * B.bind
30    | Bind_ of int * B.id * B.term * B.term
31
32 type ho_whd_result =
33    | Sort of int
34    | Abst of B.term
35
36 (* Internal functions *******************************************************)
37
38 let level = 5
39
40 let error i = raise (LRefNotFound (L.items1 (string_of_int i)))
41
42 let empty_machine = {c = B.empty_context; s = []}
43
44 let contents f c m =
45    let f gl ges = B.contents (f gl ges) m.c in
46    B.contents f c
47
48 let unwind_to_context f c m = B.append f c m.c
49
50 let unwind_to_term f m t =
51    let map f t (l, id, b) = f (B.Bind (l, id, b, t)) in
52    let f mc = C.list_fold_left f map t mc in
53    B.contents f m.c
54
55 let get f c m i =
56    let f = function
57       | Some (_, b) -> f b
58       | None        -> error i
59    in
60    let f c = B.get f c i in
61    unwind_to_context f c m
62
63 let push f c m l id w = 
64    assert (m.s = []);
65    let f w = B.push f c l id (B.Abst w) in
66    unwind_to_term f m w
67
68 (* to share *)
69 let rec whd f c m x = match x with
70    | B.Sort h                    -> f m (Sort_ h)
71    | B.GRef uri                  ->
72       let f (i, _, b) = f m (GRef_ (i, b)) in
73       E.get_obj f uri
74    | B.LRef i                    ->
75       let f = function
76          | B.Void   -> f m (LRef_ (i, None))
77          | B.Abst t -> f m (LRef_ (i, Some t))
78          | B.Abbr t -> whd f c m t
79       in
80       get f c m i
81    | B.Cast (_, t)               -> whd f c m t
82    | B.Appl (v, t)               -> whd f c {m with s = v :: m.s} t   
83    | B.Bind (l, id, B.Abst w, t) -> 
84       begin match m.s with
85          | []      -> f m (Bind_ (l, id, w, t))
86          | v :: tl -> 
87             let f mc = whd f c {c = mc; s = tl} t in
88             B.push f m.c l id (B.Abbr (B.Cast (w, v)))
89       end
90    | B.Bind (l, id, b, t)         -> 
91       let f mc = whd f c {m with c = mc} t in
92       B.push f m.c l id b
93
94 (* Interface functions ******************************************************)
95
96 let rec ho_whd f c m x =
97    let aux m = function
98       | Sort_ h             -> f c (Sort h)
99       | Bind_ (_, _, w, _)  -> 
100          let f c = f c (Abst w) in unwind_to_context f c m
101       | LRef_ (_, Some w)   -> ho_whd f c m w
102       | GRef_ (_, B.Abst u) -> ho_whd f c m u
103       | GRef_ (_, B.Abbr t) -> ho_whd f c m t
104       | LRef_ (_, None)     -> assert false
105       | GRef_ (_, B.Void)   -> assert false
106    in
107    whd aux c m x
108    
109 let ho_whd f c t =
110    let f c r = L.unbox (); f c r in
111    L.box (); L.log O.specs level (L.ct_items1 "Now scanning" c t);
112    ho_whd f c empty_machine t
113
114 let rec are_convertible f c m1 t1 m2 t2 =
115    let rec aux m1 r1 m2 r2 = match r1, r2 with
116       | Sort_ h1, Sort_ h2                               -> f (h1 = h2)
117       | LRef_ (i1, _), LRef_ (i2, _)                     ->
118          if i1 = i2 then are_convertible_stacks f c m1 m2 else f false
119       | GRef_ (a1, B.Abst _), GRef_ (a2, B.Abst _)       ->
120          if a1 = a2 then are_convertible_stacks f c m1 m2 else f false
121       | GRef_ (a1, B.Abbr v1), GRef_ (a2, B.Abbr v2)     ->
122          if a1 = a2 then are_convertible_stacks f c m1 m2 else
123          if a1 < a2 then whd (aux m1 r1) c m2 v2 else
124          whd (aux_rev m2 r2) c m1 v1
125       | _, GRef_ (_, B.Abbr v2)                          ->
126          whd (aux m1 r1) c m2 v2
127       | GRef_ (_, B.Abbr v1), _                          ->
128          whd (aux_rev m2 r2) c m1 v1      
129       | Bind_ (l1, id1, w1, t1), Bind_ (l2, id2, w2, t2) ->
130          let f b = 
131             if b then 
132                let f c = 
133                   S.subst (are_convertible f c m1 t1 m2) l1 l2 t2
134                in
135                push f c m1 l1 id1 w1
136             else f false
137          in
138          are_convertible f c m1 w1 m2 w2
139       | _                                                -> f false
140    and aux_rev m2 r2 m1 r1 = aux m1 r1 m2 r2 in
141    let f m1 r1 = whd (aux m1 r1) c m2 t2 in 
142    whd f c m1 t1
143
144 and are_convertible_stacks f c m1 m2 =
145    let mm1, mm2 = {m1 with s = []}, {m2 with s = []} in
146    let map f v1 v2 = are_convertible f c mm1 v1 mm2 v2 in
147    if List.length m1.s <> List.length m2.s then f false else
148    C.forall2 f map m1.s m2.s
149
150 let are_convertible f c t1 t2 = 
151    let f b = L.unbox (); f b in
152    L.box ();
153    L.log O.specs level (L.ct_items2 "Now converting" c t1 "and" c t2);
154    are_convertible f c empty_machine t1 empty_machine t2