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