@@ -17,8 +17,22 @@ module Elpi_AUX = struct
17
17
let s, l, _ = Utils. map_acc f s l in
18
18
s, l
19
19
20
+ let loc_of_pos = function
21
+ | None -> Ast.Loc. initial " (elpi)"
22
+ | Some x ->
23
+ let { Pos. fname; start_line; start_col; _ } = Lazy. force x in
24
+ {
25
+ Ast.Loc. source_name = Extra.Option. get " (.)" fname;
26
+ source_start = 0 ;
27
+ source_stop = 0 ;
28
+ line = start_line;
29
+ line_starts_at = start_col;
30
+ }
31
+
20
32
end
21
33
34
+ (* * Terms.sym is exposed to Elpi as an opaque data type (no syntax like int or
35
+ string). APIs are provided to manipulate symbols, eg get their type *)
22
36
let sym : Terms.sym Conversion.t = OpaqueData. declare {
23
37
OpaqueData. name = " symbol" ;
24
38
doc = " A symbol" ;
@@ -29,23 +43,32 @@ let sym : Terms.sym Conversion.t = OpaqueData.declare {
29
43
constants = [] ;
30
44
}
31
45
46
+ (* * Waiting for a ppx to do all the work for us, we code by hand the
47
+ conversion of Terms.term *)
48
+
49
+ (* Allocate Elpi symbols for the term constructors (type and kind are Elpi
50
+ keywords, hence typ and kin) *)
32
51
let typec = RawData.Constants. declare_global_symbol " typ"
33
52
let kindc = RawData.Constants. declare_global_symbol " kin"
34
53
let symbc = RawData.Constants. declare_global_symbol " symb"
35
54
let prodc = RawData.Constants. declare_global_symbol " prod"
36
55
let abstc = RawData.Constants. declare_global_symbol " abst"
37
56
let applc = RawData.Constants. declare_global_symbol " appl"
38
57
58
+ (* A two way map linking Elpi's unification variable and Terms.meta.
59
+ An instance of this map is part of the Elpi state (threaded by many
60
+ APIs) *)
39
61
module M = struct
40
62
type t = Terms .meta
41
63
let compare m1 m2 = Stdlib. compare m1.Terms. meta_key m2.Terms. meta_key
42
64
let pp = Print. pp_meta
43
65
let show m = Format. asprintf " %a" pp m
44
66
end
45
67
module MM = FlexibleData. Map (M )
46
-
47
68
let metamap : MM.t State.component = MM. uvmap
48
69
70
+ (* Terms.term -> Data.term, we use Ctxt.ctxt to carry a link between
71
+ Bindlib's var to Elpi's De Duijn levels *)
49
72
let embed_term : Terms.term Conversion.embedding = fun ~depth st t ->
50
73
let open RawData in
51
74
let open Terms in
@@ -93,6 +116,8 @@ let embed_term : Terms.term Conversion.embedding = fun ~depth st t ->
93
116
let st, t = aux ~depth [] st t in
94
117
st, t, List. rev ! gls
95
118
119
+ (* Data.term -> Terms.term. We use and IntMap to link Elpi's De Bruijn
120
+ levels to Bindlib's var *)
96
121
let readback_term_box : Terms.term Bindlib.box Conversion.readback =
97
122
fun ~depth st t ->
98
123
let open RawData in
@@ -152,6 +177,7 @@ let readback_term ~depth st t =
152
177
let st, t, gls = readback_term_box ~depth st t in
153
178
st, Bindlib. unbox t, gls
154
179
180
+ (* * Terms.term has a HOAS *)
155
181
let term : Terms.term Conversion.t = {
156
182
Conversion. ty = Conversion. TyName " term" ;
157
183
pp = Print. pp_term;
@@ -168,6 +194,8 @@ type prod term -> (term -> term) -> term.
168
194
embed = embed_term ;
169
195
}
170
196
197
+ (* * Assignments to Elpi's unification variables are a spine of lambdas
198
+ followed by an actual term. We read them back as a Bindlib.mbinder *)
171
199
let readback_mbinder st t =
172
200
let open RawData in
173
201
let rec aux ~depth nvars t =
@@ -181,8 +209,6 @@ let readback_mbinder st t =
181
209
st, unbox (bind_mvar vs t)
182
210
in
183
211
aux ~depth: 0 0 t
184
-
185
-
186
212
let readback_assignments st =
187
213
let mmap = State. get metamap st in
188
214
MM. fold (fun meta _flex body st ->
@@ -198,6 +224,7 @@ let readback_assignments st =
198
224
st
199
225
) mmap st
200
226
227
+ (* * APIs (data types and predicates) exposed to Elpi *)
201
228
let lambdapi_builtin_declarations : BuiltIn.declaration list =
202
229
let open BuiltIn in
203
230
let open BuiltInPredicate in
@@ -232,51 +259,44 @@ let lambdapi_builtin_declarations : BuiltIn.declaration list =
232
259
let lambdapi_builtins =
233
260
BuiltIn. declare ~file_name: " lambdap.elpi" lambdapi_builtin_declarations
234
261
235
- let elpi = ref None
236
-
237
262
let document () =
238
263
BuiltIn. document_file ~header: " % automatically generated" lambdapi_builtins
239
264
265
+ (* * The runtime of Elpi (we need only one I guess) *)
266
+ let elpi = ref None
267
+
240
268
let init () =
241
269
let e, _ = Setup. init ~builtins: [lambdapi_builtins] ~basedir: " ." [] in
242
270
elpi := Some e ;
243
271
document ()
244
272
245
- let loc_of_pos = function
246
- | None -> Ast.Loc. initial " (elpi)"
247
- | Some x ->
248
- let { Pos. fname; start_line; start_col; _ } = Lazy. force x in
249
- {
250
- Ast.Loc. source_name = Extra.Option. get " (.)" fname;
251
- source_start = 0 ;
252
- source_stop = 0 ;
253
- line = start_line;
254
- line_starts_at = start_col;
255
- }
256
-
273
+ (* * Given an Elpi file, a predicate name and a Terms.term argument we
274
+ run Elpi and print the term before/after the execution *)
257
275
let run : Sig_state.t -> string -> string -> Syntax.p_term -> unit =
258
276
fun ss file predicate arg ->
259
277
let pos = arg.Pos. pos in
278
+ let loc = Elpi_AUX. loc_of_pos pos in
260
279
let arg = Scope. scope_term Public ss Env. empty arg in
261
280
let elpi = match ! elpi with None -> assert false | Some x -> x in
281
+
262
282
let ast = Parse. program ~elpi [file] in
263
283
let prog =
264
284
Elpi.API.Compile. program
265
285
~flags: Elpi.API.Compile. default_flags ~elpi [ast] in
266
- let loc = loc_of_pos pos in
267
- let arguments = Query. (D (term,arg,N )) in
268
- let query = Query. (compile prog loc (Query { predicate; arguments })) in
286
+ let query =
287
+ let open Query in
288
+ compile prog loc (Query { predicate; arguments = D (term,arg,N ) }) in
289
+
269
290
if not (Elpi.API.Compile. static_check
270
291
~checker: (Elpi.Builtin. default_checker () ) query) then
271
- Console. fatal pos " elpi: type error" ;
272
- let exe = Elpi.API.Compile. optimize query in
273
- Format. printf " \n elpi: before: %a\n " Print. pp_term arg;
274
- match Execute. once exe with
292
+ Console. fatal pos " elpi: type error in %s " file ;
293
+
294
+ Console. out 1 " \n elpi: before: %a\n " Print. pp_term arg;
295
+ match Execute. once ( Elpi.API.Compile. optimize query) with
275
296
| Execute. Success { Data. state; pp_ctx; constraints; _ } ->
276
297
let _ = readback_assignments state in
277
- Format. printf " \n elpi: after: %a\n "
278
- Print. pp_term arg;
279
- Format. printf " elpi: constraints: %a\n "
298
+ Console. out 1 " \n elpi: after: %a\n " Print. pp_term arg;
299
+ Console. out 1 " elpi: constraints: %a\n "
280
300
Pp. (constraints pp_ctx) constraints
281
301
| Failure -> Console. fatal_no_pos " elpi: failure"
282
302
| NoMoreSteps -> assert false
0 commit comments