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
195
196
197
198
199
200
201
202
203
204
205
open Kernel
open Basic
open Term
open Rule
open Typing
open Parsers
exception DebugFlagNotRecognized of char
let set_debug_mode =
String.iter (function
| 'q' -> Debug.disable_flag Debug.d_warn
| 'n' -> Debug.enable_flag Debug.d_notice
| 'o' -> Debug.enable_flag Signature.d_module
| 'c' -> Debug.enable_flag Confluence.d_confluence
| 'u' -> Debug.enable_flag Typing.d_rule
| 't' -> Debug.enable_flag Typing.d_typeChecking
| 's' -> Debug.enable_flag Srcheck.d_SR
| 'r' -> Debug.enable_flag Reduction.d_reduce
| 'm' -> Debug.enable_flag Matching.d_matching
| c -> raise (DebugFlagNotRecognized c))
type t = {
input : Parser.input;
sg : Signature.t;
red : (module Reduction.S);
typer : (module Typing.S);
}
let dummy ?(md = Basic.mk_mident "") () =
let dummy_sig = Signature.make md (fun _ _ -> "") in
{
input = Parser.input_from_string md "";
sg = dummy_sig;
red = (module Reduction.Default);
typer = (module Typing.Default);
}
exception Env_error of t * loc * exn
let get_input env = env.input
let check_arity = ref true
let check_ll = ref false
let init input =
let sg = Signature.make (Parser.md_of_input input) Files.find_object_file in
let red : (module Reduction.S) = (module Reduction.Default) in
let typer : (module Typing.S) = (module Typing.Default) in
{input; sg; red; typer}
let set_reduction_engine env (module R : Reduction.S) =
let red = (module R : Reduction.S) in
let typer = (module Typing.Make (R) : Typing.S) in
{env with red; typer}
let get_reduction_engine env = env.red
let get_name env = Signature.get_name env.sg
let get_filename env =
match Parser.file_of_input env.input with
| None -> "<not a file>"
| Some f -> f
let get_signature env = env.sg
let get_printer env : (module Pp.Printer) =
(module Pp.Make (struct
let get_name () = get_name env
end))
module HName = Hashtbl.Make (struct
type t = name
let equal = name_eq
let hash = Hashtbl.hash
end)
let get_symbols env =
let table = HName.create 11 in
Signature.iter_symbols (fun md id -> HName.add table (mk_name md id)) env.sg;
table
let get_type env lc cst = Signature.get_type env.sg lc cst
let get_dtree env lc cst = Signature.get_dtree env.sg lc cst
let export env =
let file = Files.object_file_of_input env.input in
let oc = open_out file in
Signature.export env.sg oc;
close_out oc;
close_out oc
let import env lc md = Signature.import env.sg lc md
let is_injective env lc cst = Signature.is_injective env.sg lc cst
let is_static env lc cst = Signature.is_static env.sg lc cst
let _add_rules env rs =
let ris = List.map Rule.to_rule_infos rs in
if !check_arity then List.iter Rule.check_arity ris;
if !check_ll then List.iter Rule.check_linearity ris;
Signature.add_rules env.sg ris
let _declare env lc (id : ident) scope st ty : unit =
let (module T) = env.typer in
Signature.add_declaration env.sg lc id scope st
(match (T.inference env.sg ty, st) with
| Kind, Definable AC | Kind, Definable (ACU _) ->
raise (Typing_error (SortExpected (ty, [], mk_Kind)))
| Type _, Definable AC -> mk_Arrow dloc ty (mk_Arrow dloc ty ty)
| Type _, Definable (ACU neu) ->
ignore (T.checking env.sg neu ty);
mk_Arrow dloc ty (mk_Arrow dloc ty ty)
| Kind, _ | Type _, _ -> ty
| s, _ -> raise (Typing_error (SortExpected (ty, [], s))))
let declare env lc id scope st ty : unit = _declare env lc id scope st ty
let _define env lc (id : ident) (scope : Signature.scope) (opaque : bool)
(te : term) (ty_opt : Typing.typ option) : unit =
let (module T) = env.typer in
let ty =
match ty_opt with
| None -> T.inference env.sg te
| Some ty -> T.checking env.sg te ty; ty
in
match ty with
| Kind -> raise @@ Typing_error (InexpectedKind (te, []))
| _ ->
if opaque then
Signature.add_declaration env.sg lc id scope Signature.Static ty
else
let _ =
Signature.add_declaration env.sg lc id scope
(Signature.Definable Free) ty
in
let cst = mk_name (get_name env) id in
let rule =
{name = Delta cst; ctx = []; pat = Pattern (lc, cst, []); rhs = te}
in
_add_rules env [rule]
let define env lc id scope op te ty_opt : unit =
_define env lc id scope op te ty_opt
let add_rules env (rules : partially_typed_rule list) :
(Exsubst.ExSubst.t * typed_rule) list =
let (module T) = env.typer in
let rs2 = List.map (T.check_rule env.sg) rules in
_add_rules env rules; rs2
let infer env ?(ctx = []) te =
let (module T) = env.typer in
let ty = T.infer env.sg ctx te in
if ty <> mk_Kind then ignore (T.infer env.sg ctx ty);
ty
let check env ?(ctx = []) te ty =
let (module T) = env.typer in
T.check env.sg ctx te ty
let _unsafe_reduction env red te =
let (module R) = env.red in
R.reduction red env.sg te
let _reduction env ctx red te =
let (module T) = env.typer in
if te <> mk_Kind then ignore (T.infer env.sg ctx te);
_unsafe_reduction env red te
let reduction env ?(ctx = []) ?(red = Reduction.default_cfg) te =
_reduction env ctx red te
let unsafe_reduction env ?(red = Reduction.default_cfg) te =
_unsafe_reduction env red te
let are_convertible env ?(ctx = []) te1 te2 =
let (module T) = env.typer in
let (module R) = env.red in
let ty1 = T.infer env.sg ctx te1 in
let ty2 = T.infer env.sg ctx te2 in
R.are_convertible env.sg ty1 ty2 && R.are_convertible env.sg te1 te2
let errors_in_snf = ref false
let fail_env_error : t -> Basic.loc -> exn -> 'a =
fun env lc exn ->
let snf env t = if !errors_in_snf then unsafe_reduction env t else t in
let file = get_filename env in
let code, lc, msg = Errors.string_of_exception ~red:(snf env) lc exn in
Errors.fail_exit ~file ~code:(string_of_int code) (Some lc) "%s" msg