Source file term.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
open Basic
open Format
(** {2 Terms/Patterns} *)
type term =
| Kind
| Type of loc
| DB of loc * ident * int
| Const of loc * name
| App of term * term * term list
| Lam of loc * ident * term option * term
| Pi of loc * ident * term * term
let rec pp_term fmt te =
match te with
| Kind -> fprintf fmt "Kind"
| Type _ -> fprintf fmt "Type"
| DB (_, x, n) -> fprintf fmt "%a[%i]" pp_ident x n
| Const (_, n) -> fprintf fmt "%a" pp_name n
| App (f, a, args) -> pp_list " " pp_term_wp fmt (f :: a :: args)
| Lam (_, x, None, f) -> fprintf fmt "%a => %a" pp_ident x pp_term f
| Lam (_, x, Some a, f) ->
fprintf fmt "%a:%a => %a" pp_ident x pp_term_wp a pp_term f
| Pi (_, x, a, b) when ident_eq x dmark ->
fprintf fmt "%a -> %a" pp_term_wp a pp_term b
| Pi (_, x, a, b) ->
fprintf fmt "%a:%a -> %a" pp_ident x pp_term_wp a pp_term b
and pp_term_wp fmt te =
match te with
| (Kind | Type _ | DB _ | Const _) as t -> pp_term fmt t
| t -> fprintf fmt "(%a)" pp_term t
let rec get_loc (te : term) : loc =
match te with
| Type l | DB (l, _, _) | Const (l, _) | Lam (l, _, _, _) | Pi (l, _, _, _) ->
l
| Kind -> dloc
| App (f, _, _) -> get_loc f
let mk_Kind = Kind
let mk_Type l = Type l
let mk_DB l x n = DB (l, x, n)
let mk_Const l n = Const (l, n)
let mk_Lam l x a b = Lam (l, x, a, b)
let mk_Pi l x a b = Pi (l, x, a, b)
let mk_Arrow l a b = Pi (l, dmark, a, b)
let mk_App f a1 args =
match f with
| App (f', a1', args') -> App (f', a1', args' @ (a1 :: args))
| _ -> App (f, a1, args)
let mk_App2 f = function [] -> f | hd :: tl -> mk_App f hd tl
let rec add_n_lambdas n t =
if n = 0 then t else add_n_lambdas (n - 1) (mk_Lam dloc dmark None t)
let rec term_eq t1 t2 =
match (t1, t2) with
| Kind, Kind | Type _, Type _ -> true
| DB (_, _, n), DB (_, _, n') -> n == n'
| Const (_, cst), Const (_, cst') -> name_eq cst cst'
| App (f, a, l), App (f', a', l') -> (
try List.for_all2 term_eq (f :: a :: l) (f' :: a' :: l') with _ -> false)
| Lam (_, _, _, b), Lam (_, _, _, b') -> term_eq b b'
| Pi (_, _, a, b), Pi (_, _, a', b') -> term_eq a a' && term_eq b b'
| _, _ -> false
type 'a comparator = 'a -> 'a -> int
let rec compare_term id_comp t1 t2 =
match (t1, t2) with
| Kind, Kind -> 0
| Type _, Type _ -> 0
| Const (_, name), Const (_, name') -> id_comp name name'
| DB (_, _, n), DB (_, _, n') -> compare n n'
| App (f, a, ar), App (f', a', ar') ->
let c = compare_term id_comp f f' in
if c <> 0 then c
else
let c = compare_term id_comp a a' in
if c <> 0 then c else compare_term_list id_comp ar ar'
| Lam (_, _, _, t), Lam (_, _, _, t') -> compare_term id_comp t t'
| Pi (_, _, a, b), Pi (_, _, a', b') ->
let c = compare_term id_comp a a' in
if c = 0 then compare_term id_comp b b' else c
| _, Kind -> 1
| Kind, _ -> -1
| _, Type _ -> 1
| Type _, _ -> -1
| _, Const _ -> 1
| Const _, _ -> -1
| _, DB _ -> 1
| DB _, _ -> -1
| _, App _ -> 1
| App _, _ -> -1
| _, Lam _ -> 1
| Lam _, _ -> -1
and compare_term_list id_comp a b =
match (a, b) with
| [], [] -> 0
| _, [] -> 1
| [], _ -> -1
| h :: t, h' :: t' ->
let c = compare_term id_comp h h' in
if c = 0 then compare_term_list id_comp t t' else c
type algebra = Free | AC | ACU of term
let is_AC = function AC -> true | ACU _ -> true | Free -> false
type position = int list
exception InvalidSubterm of term * int
let subterm t i =
match t with
| App (f, _, _) when i = 0 -> f
| App (_, a, _) when i = 1 -> a
| App (_, _, args) -> (
try List.nth args (i - 2) with _ -> raise (InvalidSubterm (t, i)))
| Lam (_, _, _, f) when i = 1 -> f
| Lam (_, _, Some a, _) when i = 0 -> a
| Pi (_, _, a, _) when i = 0 -> a
| Pi (_, _, _, b) when i = 1 -> b
| _ -> raise (InvalidSubterm (t, i))
let subterm = List.fold_left subterm
type cstr = int * term * term
let pp_cstr fmt (depth, t1, t2) =
Format.fprintf fmt "[%i] %a = %a" depth pp_term t1 pp_term t2
type 'a context = (loc * ident * 'a) list
type partially_typed_context = term option context
type typed_context = term context
type arity_context = int context
type 'a depthed = int * 'a
let pp_untyped_ident fmt (_, id, _) = Format.fprintf fmt "%a" pp_ident id
let pp_typed_ident fmt (_, id, ty) =
Format.fprintf fmt "%a:%a" pp_ident id pp_term ty
let pp_maybe_typed_ident fmt (l, id, ty) =
match ty with
| None -> pp_untyped_ident fmt (l, id, ())
| Some ty -> pp_typed_ident fmt (l, id, ty)
let pp_context pp_i fmt l = fprintf fmt "[%a]" (pp_list ", " pp_i) (List.rev l)
let pp_untyped_context fmt = pp_context pp_untyped_ident fmt
let pp_typed_context = pp_context pp_typed_ident
let pp_part_typed_context = pp_context pp_maybe_typed_ident
let get_name_from_typed_ctxt ctxt i =
try
let _, v, _ = List.nth ctxt i in
Some v
with Failure _ -> None
let rename_vars_with_typed_context ctxt t =
let rec aux d t =
match t with
| DB (l, _, n) when n > d -> (
match get_name_from_typed_ctxt ctxt (n - d) with
| Some v' -> mk_DB l v' n
| None -> t)
| App (f, a, args) -> mk_App (aux d f) (aux d a) (List.map (aux d) args)
| Lam (l, x, ty, f) -> mk_Lam l x (map_opt (aux d) ty) (aux (d + 1) f)
| Pi (l, x, ty, b) -> mk_Pi l x (aux d ty) (aux (d + 1) b)
| _ -> t
in
aux 0 t