Skip to content

Commit c6ef22f

Browse files
committed
[elpi] documentation and cleanup
1 parent 46e19ef commit c6ef22f

File tree

1 file changed

+47
-27
lines changed

1 file changed

+47
-27
lines changed

src/core/elpi_lambdapi.ml

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,22 @@ module Elpi_AUX = struct
1717
let s, l, _ = Utils.map_acc f s l in
1818
s, l
1919

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+
2032
end
2133

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 *)
2236
let sym : Terms.sym Conversion.t = OpaqueData.declare {
2337
OpaqueData.name = "symbol";
2438
doc = "A symbol";
@@ -29,23 +43,32 @@ let sym : Terms.sym Conversion.t = OpaqueData.declare {
2943
constants = [];
3044
}
3145

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) *)
3251
let typec = RawData.Constants.declare_global_symbol "typ"
3352
let kindc = RawData.Constants.declare_global_symbol "kin"
3453
let symbc = RawData.Constants.declare_global_symbol "symb"
3554
let prodc = RawData.Constants.declare_global_symbol "prod"
3655
let abstc = RawData.Constants.declare_global_symbol "abst"
3756
let applc = RawData.Constants.declare_global_symbol "appl"
3857

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) *)
3961
module M = struct
4062
type t = Terms.meta
4163
let compare m1 m2 = Stdlib.compare m1.Terms.meta_key m2.Terms.meta_key
4264
let pp = Print.pp_meta
4365
let show m = Format.asprintf "%a" pp m
4466
end
4567
module MM = FlexibleData.Map(M)
46-
4768
let metamap : MM.t State.component = MM.uvmap
4869

70+
(* Terms.term -> Data.term, we use Ctxt.ctxt to carry a link between
71+
Bindlib's var to Elpi's De Duijn levels *)
4972
let embed_term : Terms.term Conversion.embedding = fun ~depth st t ->
5073
let open RawData in
5174
let open Terms in
@@ -93,6 +116,8 @@ let embed_term : Terms.term Conversion.embedding = fun ~depth st t ->
93116
let st, t = aux ~depth [] st t in
94117
st, t, List.rev !gls
95118

119+
(* Data.term -> Terms.term. We use and IntMap to link Elpi's De Bruijn
120+
levels to Bindlib's var *)
96121
let readback_term_box : Terms.term Bindlib.box Conversion.readback =
97122
fun ~depth st t ->
98123
let open RawData in
@@ -152,6 +177,7 @@ let readback_term ~depth st t =
152177
let st, t, gls = readback_term_box ~depth st t in
153178
st, Bindlib.unbox t, gls
154179

180+
(** Terms.term has a HOAS *)
155181
let term : Terms.term Conversion.t = {
156182
Conversion.ty = Conversion.TyName "term";
157183
pp = Print.pp_term;
@@ -168,6 +194,8 @@ type prod term -> (term -> term) -> term.
168194
embed = embed_term;
169195
}
170196

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 *)
171199
let readback_mbinder st t =
172200
let open RawData in
173201
let rec aux ~depth nvars t =
@@ -181,8 +209,6 @@ let readback_mbinder st t =
181209
st, unbox (bind_mvar vs t)
182210
in
183211
aux ~depth:0 0 t
184-
185-
186212
let readback_assignments st =
187213
let mmap = State.get metamap st in
188214
MM.fold (fun meta _flex body st ->
@@ -198,6 +224,7 @@ let readback_assignments st =
198224
st
199225
) mmap st
200226

227+
(** APIs (data types and predicates) exposed to Elpi *)
201228
let lambdapi_builtin_declarations : BuiltIn.declaration list =
202229
let open BuiltIn in
203230
let open BuiltInPredicate in
@@ -232,51 +259,44 @@ let lambdapi_builtin_declarations : BuiltIn.declaration list =
232259
let lambdapi_builtins =
233260
BuiltIn.declare ~file_name:"lambdap.elpi" lambdapi_builtin_declarations
234261

235-
let elpi = ref None
236-
237262
let document () =
238263
BuiltIn.document_file ~header:"% automatically generated" lambdapi_builtins
239264

265+
(** The runtime of Elpi (we need only one I guess) *)
266+
let elpi = ref None
267+
240268
let init () =
241269
let e, _ = Setup.init ~builtins:[lambdapi_builtins] ~basedir:"." [] in
242270
elpi := Some e;
243271
document ()
244272

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 *)
257275
let run : Sig_state.t -> string -> string -> Syntax.p_term -> unit =
258276
fun ss file predicate arg ->
259277
let pos = arg.Pos.pos in
278+
let loc = Elpi_AUX.loc_of_pos pos in
260279
let arg = Scope.scope_term Public ss Env.empty arg in
261280
let elpi = match !elpi with None -> assert false | Some x -> x in
281+
262282
let ast = Parse.program ~elpi [file] in
263283
let prog =
264284
Elpi.API.Compile.program
265285
~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+
269290
if not (Elpi.API.Compile.static_check
270291
~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 "\nelpi: 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 "\nelpi: before: %a\n" Print.pp_term arg;
295+
match Execute.once (Elpi.API.Compile.optimize query) with
275296
| Execute.Success { Data.state; pp_ctx; constraints; _ } ->
276297
let _ = readback_assignments state in
277-
Format.printf "\nelpi: after: %a\n"
278-
Print.pp_term arg;
279-
Format.printf "elpi: constraints: %a\n"
298+
Console.out 1 "\nelpi: after: %a\n" Print.pp_term arg;
299+
Console.out 1 "elpi: constraints: %a\n"
280300
Pp.(constraints pp_ctx) constraints
281301
| Failure -> Console.fatal_no_pos "elpi: failure"
282302
| NoMoreSteps -> assert false

0 commit comments

Comments
 (0)