Source file subst.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
open Basic
open Term
exception UnshiftExn
type substitution = loc -> ident -> int -> int -> term
let apply_subst (subst : substitution) : int -> term -> term =
let ct = ref 0 in
let rec aux k t =
match t with
| DB (l, x, n) when n >= k -> (
try
let res = subst l x n k in
incr ct; res
with Not_found -> t)
| App (f, a, args) ->
let ct' = !ct in
let f', a', args' = (aux k f, aux k a, List.map (aux k) args) in
if !ct = ct' then t else mk_App f' a' args'
| Lam (l, x, a, f) ->
let ct' = !ct in
let a', f' = (map_opt (aux k) a, aux (k + 1) f) in
if !ct = ct' then t else mk_Lam l x a' f'
| Pi (l, x, a, b) ->
let ct' = !ct in
let a', b' = (aux k a, aux (k + 1) b) in
if !ct = ct' then t else mk_Pi l x a' b'
| _ -> t
in
aux
let shift r t =
if r = 0 then t else apply_subst (fun l x n _ -> mk_DB l x (n + r)) 0 t
let unshift q =
apply_subst
(fun l x n k -> if n < q + k then raise UnshiftExn else mk_DB l x (n - q))
0
let psubst_l (args : term Lazy.t LList.t) : term -> term =
let nargs = LList.len args in
let tab = Array.make nargs [] in
let rec get i k =
let l = tab.(i) in
try List.assoc k l
with Not_found ->
if k == 0 then Lazy.force (LList.nth args i)
else
let res = shift k (get i 0) in
tab.(i) <- (k, res) :: l;
res
in
let subst l x n k =
if n >= k + nargs then mk_DB l x (n - nargs) else get (n - k) k
in
apply_subst subst 0
let subst (te : term) (u : term) =
apply_subst
(fun l x n k -> if n = k then shift k u else mk_DB l x (n - 1))
0 te
let subst_n m y =
apply_subst
(fun l x n k -> if n = m + k then mk_DB l y k else mk_DB l x (n + 1))
0
let occurs (n : int) (te : term) : bool =
let exception Occurs in
let rec aux depth = function
| Kind | Type _ | Const _ -> ()
| DB (_, _, k) -> if k = n + depth then raise Occurs else ()
| App (f, a, args) -> List.iter (aux depth) (f :: a :: args)
| Lam (_, _, None, te) -> aux (depth + 1) te
| Lam (_, _, Some ty, te) ->
aux depth ty;
aux (depth + 1) te
| Pi (_, _, a, b) ->
aux depth a;
aux (depth + 1) b
in
try aux 0 te; false with Occurs -> true