-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdebruijn.ml
173 lines (144 loc) · 4.82 KB
/
debruijn.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
(* --- DeBruijn management --- *)
open Environ
open Constr
open Utilities
open Envutils
open Hofs
(* --- Numbers --- *)
(* Unshift an index by n *)
let unshift_i_by (n : int) (i : int) : int =
i - n
(* Shift an index by n *)
let shift_i_by (n : int) (i : int) : int =
unshift_i_by (- n) i
(* Unshift an index *)
let unshift_i (i : int) : int =
unshift_i_by 1 i
(* Shift an index *)
let shift_i (i : int) : int =
shift_i_by 1 i
(* --- Terms --- *)
(*
* Unshifts a term by n if it is greater than the maximum index
* max of a local binding
*)
let unshift_local (max : int) (n : int) (trm : types) : types =
map_term
(fun (m, adj) t ->
match kind t with
| Rel i ->
let i' = if i > m then unshift_i_by adj i else i in
mkRel i'
| _ ->
t)
(fun (m, adj) -> (shift_i m, adj))
(max, n)
trm
(*
* Shifts a term by n if it is greater than the maximum index
* max of a local binding
*)
let shift_local (max : int) (n : int) (trm : types) : types =
unshift_local max (- n) trm
(* Decrement the relative indexes of a term t by n *)
let unshift_by (n : int) (trm : types) : types =
unshift_local 0 n trm
(* Increment the relative indexes of a term t by n *)
let shift_by (n : int) (t : types) : types =
unshift_by (- n) t
(* Increment the relative indexes of a term t by one *)
let shift (t : types) : types =
shift_by 1 t
(* Decrement the relative indexes of a term t by one *)
let unshift (t : types) : types =
unshift_by 1 t
(* Shift everything and pray; workaround for bug (TODO investigate) *)
let shift_by_unconditional (n : int) (trm : types) : types =
map_term
(fun _ t ->
match kind t with
| Rel i ->
let i' = shift_i_by n i in
mkRel i'
| _ ->
t)
(fun _ -> ())
()
trm
(*
* Function from:
* https://github.com/coq/coq/commit/7ada864b7728c9c94b7ca9856b6b2c89feb0214e
* Inlined here to make this compatible with Coq 8.8.0
* TODO remove with update
*)
let fold_constr_with_binders g f n acc c =
match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
| Construct _) -> acc
| Cast (c,_, t) -> f n (f n acc c) t
| Prod (na,t,c) -> f (g n) (f n acc t) c
| Lambda (na,t,c) -> f (g n) (f n acc t) c
| LetIn (na,b,t,c) -> f (g n) (f n (f n acc b) t) c
| App (c,l) -> Array.fold_left (f n) (f n acc c) l
| Proj (p,c) -> f n acc c
| Evar (_,l) -> Array.fold_left (f n) acc l
| Case (_,p,c,bl) -> Array.fold_left (f n) (f n (f n acc p) c) bl
| Fix (_,(lna,tl,bl)) ->
let n' = CArray.fold_left2 (fun c n t -> g c) n lna tl in
let fd = Array.map2 (fun t b -> (t,b)) tl bl in
Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
| CoFix (_,(lna,tl,bl)) ->
let n' = CArray.fold_left2 (fun c n t -> g c) n lna tl in
let fd = Array.map2 (fun t b -> (t,b)) tl bl in
Array.fold_left (fun acc (t,b) -> f n' (f n acc t) b) acc fd
(*
* Gather the set of relative (de Bruijn) variables occurring in the term that
* are free (i.e., not bound) under nb levels of external relative binding.
*
* Use free_rels 0 Int.Set.empty if you do not wish to filter out any free
* relative variables below a certain binding level (nb) or supply the initial
* accumulator (frels).
*
* Examples:
* - free_rels 0 (Lambda(_, Rel 2, App(Rel 2, [Rel 1; Rel 4]))) = { 1, 2, 3 }
* - free_rels 1 (Lambda(_, Rel 2, App(Rel 2, [Rel 1; Rel 4]))) = { 2, 3 }
* - free_rels 2 (Lambda(_, Rel 2, App(Rel 2, [Rel 1; Rel 4]))) = { 3 }
*
* Like many functions, by Nate Yazdani from original DEVOID code
*)
let rec free_rels nb frels term =
match Constr.kind term with
| Rel i ->
if i > nb then Int.Set.add (unshift_i_by nb i) frels else frels
| _ ->
fold_constr_with_binders succ free_rels nb frels term
(* --- Lists --- *)
(* Shift a list *)
let shift_all = List.map shift
(* Shift all elements of a list by n *)
let shift_all_by n = List.map (shift_by n)
(* Unshift a list *)
let unshift_all = List.map unshift
(* Unshift all elements of a list by n *)
let unshift_all_by n = List.map (unshift_by n)
(* --- Substitutions --- *)
(* Shift substitutions *)
let shift_subs = List.map (map_tuple shift)
(* Shift from substitutions *)
let shift_from = List.map (fun (s, d) -> (shift s, d))
(* Shift to substitutions *)
let shift_to = List.map (fun (s, d) -> (s, shift d))
(* --- Environments --- *)
(* Shift a term by the offset from env_o to env_n *)
let shift_to_env (env_o, env_n) trm =
shift_by (new_rels2 env_n env_o) trm
(* Unshifts indexes for terms in env by n *)
let unshift_env_by (n : int) (env : env) : env =
let num_rels = nb_rel env in
let all_relis = List.rev (from_one_to num_rels) in
let all_rels = lookup_rels all_relis env in
List.fold_left
(fun env decl ->
push_rel decl env)
(pop_rel_context num_rels env)
all_rels