]> matita.cs.unibo.it Git - fireball-separation.git/blob - ocaml/num.ml
6f3cae56c327c103eeb42c127bc626cbd28aa3eb
[fireball-separation.git] / ocaml / num.ml
1 open Util
2 open Util.Vars
3 open Pure
4
5 (************ Syntax ************************************)
6
7 (* Normal forms*)
8
9 (* Var n = n-th De Bruijn index, 0-based *)
10
11 (*type nf =
12   | Lam of nf
13   | Var of int
14   | i
15 and i =
16   | I of int * nf listx
17 ;;*)
18 type 'nf i_var_ = [ `I of int * 'nf Listx.listx | `Var of int ]
19 type 'nf i_n_var_ = [ `N of int | 'nf i_var_ ]
20 type 'nf i_num_var_ = [
21   | 'nf i_n_var_
22   | `Match of 'nf i_num_var_ * (*lift*) int * (*branches*)(int * 'nf) list ref * (*args*)'nf list
23 ]
24 type 'nf nf_ = [ `Lam of (* was_unpacked *) bool * 'nf nf_ | 'nf i_num_var_ ]
25 type nf = nf nf_
26 type i_var = nf i_var_;;
27 type i_n_var = nf i_n_var_;;
28 type i_num_var = nf i_num_var_;;
29
30 let hd_of_i_var =
31  function
32    `I (v,_)
33  | `Var v -> v
34
35 let hd_of =
36  function
37    `I (v,_)
38  | `Var v -> Some v
39  | `N _ -> None
40  | `Match _ -> assert false
41
42 let lift m (t : nf) =
43  let rec aux_i_num_var l =
44   function
45     `I(n,args) -> (`I((if n < l then n else n+m),Listx.map (aux l) args) : i_num_var)
46    | `Var n -> `Var (if n < l then n else n+m)
47    | `N _ as x -> x
48    | `Match(t,lift,bs,args) ->
49       `Match(aux_i_num_var l t, lift + m, bs, List.map (aux l) args)
50  and aux l =
51   function
52      #i_num_var as x -> (aux_i_num_var l x :> nf)
53    | `Lam(b,nf) -> `Lam (b,aux (l+1) nf)
54  in
55   (aux 0 t : nf)
56 ;;
57
58 (* put t under n lambdas, lifting t accordingtly *)
59 let rec make_lams t =
60  function
61    0 -> t
62  | n when n > 0 -> `Lam (false,lift 1 (make_lams t (n-1)))
63  | _ -> assert false
64
65 let free_vars =
66  let rec aux n = function
67     `N _ -> []
68   | `Var x -> if x < n then [] else [x-n]
69   | `I(x,args) ->
70       (if x < n then [] else [x-n]) @
71       List.concat (List.map (aux n) (Listx.to_list args))
72   | `Lam(_,t) -> aux (n+1) t
73   | `Match(t,liftno,bs,args) ->
74       aux n (t :> nf) @
75       List.concat (List.map (fun (_,t) -> aux (n-liftno) t) !bs) @
76       List.concat (List.map (aux n) args)
77   in aux 0
78 ;;
79
80 module ToScott =
81 struct
82
83 let rec t_of_i_num_var =
84  function
85   | `N n -> Scott.mk_n n
86   | `Var v -> Pure.V v
87   | `Match(t,liftno,bs,args) ->
88       let bs = List.map (fun (n,t) -> n, t_of_nf (lift liftno t)) !bs in
89       let t = t_of_i_num_var t in
90       let m = Scott.mk_match t bs in
91       List.fold_left (fun acc t -> Pure.A(acc,t_of_nf t)) m args
92   | `I(v, args) -> Listx.fold_left (fun acc t -> Pure.A(acc,t_of_nf t)) (Pure.V v) args
93 and t_of_nf =
94  function
95   | #i_num_var as x -> t_of_i_num_var x
96   | `Lam(b,f) -> Pure.L (t_of_nf f)
97
98 end
99
100
101 (************ Pretty-printing ************************************)
102
103 let rec print ?(l=[]) =
104  function
105     `Var n -> print_name l n
106   | `N n -> string_of_int n
107   | `Match(t,bs_lift,bs,args) ->
108      "([" ^ print ~l (t :> nf) ^
109      " ? " ^ String.concat " | " (List.map (fun (n,t) -> string_of_int n ^ " => " ^ print ~l (lift bs_lift t)) !bs) ^ "] " ^
110      String.concat " " (List.map (print ~l) args) ^ ")"
111   | `I(n,args) -> "(" ^ print_name l n ^ " " ^ String.concat " " (Listx.to_list (Listx.map (print ~l) args)) ^ ")"
112   | `Lam(_,nf) ->
113      let name = string_of_var (List.length l) in
114      "λ" ^ name ^ "." ^ print ~l:(name::l) (nf : nf)
115 ;;
116
117 let rec string_of_term l =
118  let rec string_of_term_w_pars l = function
119   | `Var n -> print_name l n
120   | `N n -> string_of_int n
121   | `I _ as t -> "(" ^ string_of_term_no_pars_app l (t :> nf) ^ ")"
122   | `Lam _ as t -> "(" ^ string_of_term_no_pars_lam l t ^ ")"
123   | `Match(t,bs_lift,bs,args) ->
124      "(match " ^ string_of_term_no_pars l (t :> nf) ^
125      " with " ^ String.concat " | " (List.map (fun (n,t) -> string_of_int n ^ " => " ^ string_of_term l (lift bs_lift t)) !bs) ^ "] " ^
126      String.concat " " (List.map (string_of_term l) args) ^ ")"
127  and string_of_term_no_pars_app l = function
128   | `I(n, args) -> print_name l n ^ " " ^ String.concat " " (List.map (string_of_term_w_pars l) (Listx.to_list args))
129   | #nf as t -> string_of_term_w_pars l t
130  and string_of_term_no_pars_lam l  = function
131   | `Lam(_,t) -> let name = string_of_var (List.length l) in
132    "λ" ^ name ^ ". " ^ (string_of_term_no_pars_lam (name::l) t)
133   | _ as t -> string_of_term_no_pars l t
134  and string_of_term_no_pars l : nf -> string = function
135   | `Lam _ as t -> string_of_term_no_pars_lam l t
136   | #nf as t -> string_of_term_no_pars_app l t
137  in string_of_term_no_pars l
138 ;;
139
140 let print ?(l=[]) = string_of_term l;;
141 let string_of_nf t = string_of_term [] (t:>nf);;
142
143 (************ Hereditary substitutions ************************************)
144
145 let cast_to_i_var =
146  function
147     #i_var as y -> (y : i_var)
148   | t ->
149     prerr_endline (print (t :> nf));
150     assert false (* algorithm failed *)
151
152 let cast_to_i_n_var =
153  function
154     #i_n_var as y -> (y : i_n_var)
155   | t ->
156     prerr_endline (print (t :> nf));
157     assert false (* algorithm failed *)
158
159 let cast_to_i_num_var =
160  function
161     #i_num_var as y -> (y : i_num_var)
162   | t ->
163     prerr_endline (print (t :> nf));
164     assert false (* algorithm failed *)
165
166 let rec mk_app (h : nf) (arg : nf) =
167 (*let res =*)
168  match h with
169     `I(n,args) -> `I(n,Listx.append (Listx.Nil arg) args)
170   | `Var n -> `I(n, Listx.Nil arg)
171   | `Lam(_,nf) -> subst true 0 arg (nf : nf)
172   | `Match(t,lift,bs,args) -> `Match(t,lift,bs,List.append args [arg])
173   | `N _ -> assert false (* Numbers cannot be applied *)
174 (*in let l = ["v0";"v1";"v2"] in
175 prerr_endline ("mk_app h:" ^ print ~l h ^ " arg:" ^ print ~l:l arg ^ " res:" ^ print ~l:l res); res*)
176
177 and mk_appl h args =
178  (*prerr_endline ("MK_APPL: " ^ print h ^ " " ^ String.concat " " (List.map print args));*)
179  List.fold_left mk_app h args
180
181 and mk_appx h args = Listx.fold_left mk_app h args
182
183 and mk_match t bs_lift bs args =
184  (*prerr_endline ("MK_MATCH: ([" ^ print t ^ "] " ^ String.concat " " (Listx.to_list (Listx.map (fun (n,t) -> string_of_int n ^ " => " ^ print t) bs)) ^ ") " ^ String.concat " " (List.map print args));*)
185  match t with
186     `N m ->
187       (try
188         let h = List.assoc m !bs in
189         let h = lift bs_lift h in
190         mk_appl h args
191        with Not_found ->
192         `Match (t,bs_lift,bs,args))
193   | `I _ | `Var _ | `Match _ -> `Match(t,bs_lift,bs,args)
194
195 and subst delift_by_one what (with_what : nf) (where : nf) =
196  let rec aux_i_num_var l =
197   function
198      `I(n,args) ->
199        if n = what + l then
200         mk_appx (lift l with_what) (Listx.map (aux l) args)
201        else
202         `I ((if delift_by_one && n >= l then n-1 else n), Listx.map (aux l) args)
203    | `Var n ->
204        if n = what + l then
205         lift l with_what
206        else
207         `Var (if delift_by_one && n >= l then n-1 else n)
208    | `N _ as x -> x
209    | `Match(t,bs_lift,bs,args) ->
210        let bs_lift = bs_lift + if delift_by_one then -1 else 0 in
211        let l' = l - bs_lift  in
212        let with_what' = lift l' with_what in
213        (* The following line should be the identity when delift_by_one = true because we
214           are assuming the ts to not contain lambda-bound variables. *)
215        bs := List.map (fun (n,t) -> n,subst false what with_what' t) !bs ;
216        mk_match (cast_to_i_num_var (aux_i_num_var l t)) bs_lift bs (List.map (aux l) args)
217  and aux l(*lift*) =
218 (*function iii -> let res = match iii with*)
219   function
220    | #i_num_var as x -> aux_i_num_var l x
221    | `Lam(b,nf) -> `Lam(b,aux (l+1) nf)
222 (*in let ll = ["v0";"v1";"v2"] in
223 prerr_endline ("subst l:" ^ string_of_int l ^ " delift_by_one:" ^ string_of_bool delift_by_one ^ " what:" ^ (List.nth ll what) ^ " with_what:" ^ print ~l:ll with_what ^ " where:" ^ print ~l:ll iii ^ " res:" ^ print ~l:ll res); res*)
224  in
225   aux 0 where
226 ;;
227
228 (************ Parsing ************************************)
229
230 let parse' strs =
231   let rec aux = function
232   | Parser.Lam t -> `Lam (true,aux t)
233   | Parser.App (t1, t2) -> mk_app (aux t1) (aux t2)
234   | Parser.Var v -> `Var v
235   in let (tms, free) = Parser.parse_many strs
236   in (List.map aux tms, free)
237 ;;
238
239 (************** Algorithm(s) ************************)
240
241 let eta_compare x y =
242  (* let clex a b = let diff = ? a b in if diff = 0 then cont () else 0 in *)
243  let clex aux1 aux2 (a1,a2) (b1,b2) =
244   let diff = aux1 a1 b1 in if diff = 0 then aux2 a2 b2 else diff in
245  let rec lex aux l1 l2 =
246   match l1,l2 with
247  | [], [] -> 0
248  | [], _ -> -1
249  | _, [] -> 1
250  | x::xs, y::ys -> clex aux (lex aux) (x,xs) (y,ys) in
251  let rec aux t1 t2 = match t1, t2 with
252   | `Var n , `Var m -> compare n m
253   | `I(n1, l1), `I(n2, l2) ->
254     clex compare (lex aux) (n1, Listx.to_list l1) (n2, Listx.to_list l2)
255   | `Lam _, `N _ -> -1
256   | `N _, `Lam _ -> 1
257   | `Lam(_,t1), `Lam(_,t2) -> aux t1 t2
258   | `Lam(_,t1), t2 -> - aux t1 (mk_app (lift 1 t2) (`Var 0))
259   | t2, `Lam(_,t1) ->   aux t1 (mk_app (lift 1 t2) (`Var 0))
260   | `N n1, `N n2 -> compare n1 n2
261   | `Match(u,bs_lift,bs,args), `Match(u',bs_lift',bs',args') ->
262     let bs = List.sort (fun (n,_) (m,_) -> compare n m) !bs in
263     let bs' = List.sort (fun (n,_) (m,_) -> compare n m) !bs' in
264     clex aux (clex (lex (clex compare aux)) (lex aux)) ((u :> nf), (bs, args)) ((u' :> nf), (bs', args'))
265   | `Match _, _ -> -1
266   | _, `Match _ -> 1
267   | `N _, _ -> -1
268   | _, `N _ -> 1
269   | `I _, _ -> -1
270   | _, `I _ -> 1
271   in aux x y
272 ;;
273
274 let eta_eq (#nf as x) (#nf as y) = 0 = eta_compare x y ;;
275
276 let rec eta_subterm sub t =
277  if eta_eq sub t then true else
278   match t with
279   | `Lam(_,t') -> eta_subterm (lift 1 sub) t'
280   | `Match(u,liftno,bs,args) ->
281      eta_subterm sub (u :> nf)
282      || List.exists (fun (_, t) -> eta_subterm sub (lift liftno t)) !bs
283      || List.exists (eta_subterm sub) args
284   | `I(v, args) -> List.exists (eta_subterm sub) (Listx.to_list args) || (match sub with
285    | `Var v' -> v = v'
286    | `I(v', args') -> v = v'
287     && Listx.length args' < Listx.length args
288     && List.for_all (fun (x,y) -> eta_eq x y) (List.combine (Util.take (Listx.length args') (Listx.to_list args)) (Listx.to_list args'))
289    | _ -> false
290    )
291   | `N _ | `Var _ -> false
292 ;;
293
294 let eta_subterm (#nf as x) (#nf as y) = eta_subterm x y;;