forked from LPCIC/elpi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
elpi_data.ml
694 lines (599 loc) · 21.4 KB
/
elpi_data.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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
(* elpi: embedded lambda prolog interpreter *)
(* license: GNU Lesser General Public License Version 2.1 *)
(* ------------------------------------------------------------------------- *)
(* Internal term representation *)
module Fmt = Format
module F = Elpi_ast.Func
open Elpi_util
module IM = Map.Make(struct type t = int let compare x y = x - y end)
let { CData.cin = in_float; isc = is_float; cout = out_float } as cfloat =
CData.(declare {
data_name = "float";
data_pp = (fun f x -> Fmt.fprintf f "%f" x);
data_eq = (==);
data_hash = Hashtbl.hash;
})
let { CData.cin = in_int; isc = is_int; cout = out_int } as cint =
CData.(declare {
data_name = "int";
data_pp = (fun f x -> Fmt.fprintf f "%d" x);
data_eq = (==);
data_hash = Hashtbl.hash;
})
let { CData.cin = in_string; isc = is_string; cout = out_string } as cstring =
CData.(declare {
data_name = "string";
data_pp = (fun f x -> Fmt.fprintf f "\"%s\"" (F.show x));
data_eq = (==);
data_hash = Hashtbl.hash;
})
let { CData.cin = in_loc; isc = is_loc; cout = out_loc } as cloc =
CData.(declare {
data_name = "loc";
data_pp = (fun f (x,name) ->
let bname = Filename.basename (Ploc.file_name x) in
let line_no = Ploc.line_nb x in
match name with
| None -> Fmt.fprintf f "%s:%4d:" bname line_no
| Some name -> Fmt.fprintf f "%s:%4d:%s:" bname line_no name);
data_eq = (==);
data_hash = Hashtbl.hash;
})
(******************************************************************************
Terms: data type definition and printing
******************************************************************************)
(* To break circularity, we open the index type (index of clauses) here
* and extend it with the Index constructor when such data type will be
* defined. The same for chr with CHR.t *)
type prolog_prog = ..
let pp_prolog_prog = mk_extensible_printer ()
type chr = ..
let pp_chr = mk_extensible_printer ()
(* Used by pretty printers, to be later instantiated in module Constants *)
let pp_const = mk_extensible_printer ()
type constant = int (* De Bruijn levels *)
[@printer (pp_extensible pp_const)]
[@@deriving show, eq]
(* To be instantiated after the dummy term is defined *)
let pp_oref = mk_extensible_printer ()
(* Invariant: a Heap term never points to a Query term *)
let id_term = UUID.make ()
type term =
(* Pure terms *)
| Const of constant
| Lam of term
| App of constant * term * term list
(* Clause terms: unif variables used in clauses *)
| Arg of (*id:*)int * (*argsno:*)int
| AppArg of (*id*)int * term list
(* Heap terms: unif variables in the query *)
| UVar of term_attributed_ref * (*depth:*)int * (*argsno:*)int
| AppUVar of term_attributed_ref * (*depth:*)int * term list
(* Misc: $custom predicates, ... *)
| Custom of constant * term list
| CData of CData.t
(* Optimizations *)
| Cons of term * term
| Nil
and term_attributed_ref = {
mutable contents : term [@printer (pp_extensible_any ~id:id_term pp_oref)];
mutable rest : stuck_goal list [@printer fun _ _ -> ()]
[@equal fun _ _ -> true];
}
and stuck_goal = {
mutable blockers : term_attributed_ref list;
kind : stuck_goal_kind;
}
and stuck_goal_kind =
| Constraint of constraint_def (* inline record in 4.03 *)
| Unification of unification_def
and unification_def = {
adepth : int;
env : term array;
bdepth : int;
a : term;
b : term;
}
and constraint_def = {
depth : int;
prog : prolog_prog [@equal fun _ _ -> true]
[@printer (pp_extensible pp_prolog_prog)];
pdiff : (int * term) list;
goal : term;
}
[@@deriving show, eq]
module CD = struct
let is_int = is_int
let to_int = out_int
let of_int x = CData (in_int x)
let is_float = is_float
let to_float = out_float
let of_float x = CData (in_float x)
let is_string = is_string
let to_string x = F.show (out_string x)
let of_string x = CData (in_string (F.from_string x))
end
let destConst = function Const x -> x | _ -> assert false
(* Our ref data type: creation and dereference. Assignment is defined
After the constraint store, since assigning may wake up some constraints *)
let oref x = { contents = x; rest = [] }
let (!!) { contents = x } = x
(* Arg/AppArg point to environments, here the empty one *)
type env = term array
let empty_env = [||]
(* - negative constants are global names
- constants are hashconsed (terms)
- we use special constants to represent !, pi, sigma *)
module Constants : sig
val funct_of_ast : F.t -> constant * term
val of_dbl : constant -> term
val show : constant -> string
val pp : Format.formatter -> constant -> unit
val fresh : unit -> constant * term
val from_string : string -> term
val from_stringc : string -> constant
(* To keep the type of terms small, we use special constants for !, =, pi.. *)
(* {{{ *)
val cutc : term
val truec : term
val andc : constant
val andt : term
val andc2 : constant
val orc : constant
val implc : constant
val rimplc : constant
val rimpl : term
val pic : constant
val pi : term
val sigmac : constant
val eqc : constant
val rulec : constant
val cons : term
val consc : constant
val nil : term
val nilc : constant
val entailsc : constant
val nablac : constant
val uvc : constant
val asc : constant
val letc : constant
val arrowc : constant
val ctypec : constant
val spillc : constant
(* }}} *)
(* Value for unassigned UVar/Arg *)
val dummy : term
type t = constant
val compare : t -> t -> int
module Set : Set.S with type elt = t
module Map : Map.S with type key = t
(* mkinterval d n 0 = [d; ...; d+n-1] *)
val mkinterval : int -> int -> int -> term list
end = struct (* {{{ *)
(* Hash re-consing :-( *)
let funct_of_ast, of_dbl, show, fresh =
let h = Hashtbl.create 37 in
let h' = Hashtbl.create 37 in
let h'' = Hashtbl.create 17 in
let fresh = ref 0 in
(function x ->
try Hashtbl.find h x
with Not_found ->
decr fresh;
let n = !fresh in
let xx = Const n in
let p = n,xx in
Hashtbl.add h' n (F.show x);
Hashtbl.add h'' n xx;
Hashtbl.add h x p; p),
(function x ->
try Hashtbl.find h'' x
with Not_found ->
let xx = Const x in
Hashtbl.add h' x ("x" ^ string_of_int x);
Hashtbl.add h'' x xx; xx),
(function n ->
try Hashtbl.find h' n
with Not_found -> string_of_int n),
(fun () ->
decr fresh;
let n = !fresh in
let xx = Const n in
Hashtbl.add h' n ("frozen-"^string_of_int n);
Hashtbl.add h'' n xx;
n,xx)
;;
let pp fmt c = Format.fprintf fmt "%s" (show c)
let from_stringc s = fst (funct_of_ast F.(from_string s))
let from_string s = snd (funct_of_ast F.(from_string s))
let cutc = snd (funct_of_ast F.cutf)
let truec = snd (funct_of_ast F.truef)
let andc, andt = funct_of_ast F.andf
let andc2 = fst (funct_of_ast F.andf2)
let orc = fst (funct_of_ast F.orf)
let implc = fst (funct_of_ast F.implf)
let rimplc, rimpl = funct_of_ast F.rimplf
let pic, pi = funct_of_ast F.pif
let sigmac = fst (funct_of_ast F.sigmaf)
let eqc = fst (funct_of_ast F.eqf)
let rulec = fst (funct_of_ast (F.from_string "rule"))
let nilc, nil = (funct_of_ast F.nilf)
let consc, cons = (funct_of_ast F.consf)
let nablac = fst (funct_of_ast (F.from_string "nabla"))
let entailsc = fst (funct_of_ast (F.from_string "?-"))
let uvc = fst (funct_of_ast (F.from_string "??"))
let asc = fst (funct_of_ast (F.from_string "as"))
let letc = fst (funct_of_ast (F.from_string ":="))
let spillc = fst (funct_of_ast (F.spillf))
let arrowc = fst (funct_of_ast F.arrowf)
let ctypec = fst (funct_of_ast F.ctypef)
let dummy = App (-9999,cutc,[])
module Self = struct
type t = constant
let compare x y = x - y
end
module Map = Map.Make(Self)
module Set = Set.Make(Self)
include Self
let () = extend_printer pp_const (fun fmt i ->
Fmt.fprintf fmt "%s" (show i);
`Printed)
(* mkinterval d n 0 = [d; ...; d+n-1] *)
let rec mkinterval depth argsno n =
if n = argsno then []
else of_dbl (n+depth)::mkinterval depth argsno (n+1)
;;
end (* }}} *)
module C = Constants
(* Dereferencing an UVar(r,args) when !!r != dummy requires a function
of this kind. The pretty printer needs one but will only be defined
later, since we need, for example, beta reduction to implement it *)
type 'args deref_fun =
?avoid:term_attributed_ref -> from:int -> to_:int -> 'args -> term -> term
module Pp : sig
(* Low level printing *)
val ppterm : ?min_prec:int ->
(*depth:*)int -> (*names:*)string list -> (*argsdepth:*)int -> env ->
Fmt.formatter -> term -> unit
(* For user consumption *)
val uppterm : ?min_prec:int ->
(*depth:*)int -> (*names:*)string list -> (*argsdepth:*)int -> env ->
Fmt.formatter -> term -> unit
(* To be assigned later, used to dereference an UVar/AppUVar *)
val do_deref : int deref_fun ref
val do_app_deref : term list deref_fun ref
end = struct (* {{{ *)
let do_deref = ref (fun ?avoid ~from ~to_ _ _ -> assert false);;
let do_app_deref = ref (fun ?avoid ~from ~to_ _ _ -> assert false);;
let m = ref [];;
let n = ref 0;;
let min_prec = Elpi_parser.min_precedence
let appl_prec = Elpi_parser.appl_precedence
let lam_prec = Elpi_parser.lam_precedence
let inf_prec = Elpi_parser.inf_precedence
let xppterm ~nice ?(min_prec=min_prec) depth0 names argsdepth env f t =
let pp_app f pphd pparg ?pplastarg (hd,args) =
if args = [] then pphd f hd
else
Fmt.fprintf f "@[<hov 1>%a@ %a@]" pphd hd
(pplist pparg ?pplastelem:pplastarg "") args in
let ppconstant f c = Fmt.fprintf f "%s" (C.show c) in
let rec pp_uvar prec depth vardepth args f r =
if !!r == C.dummy then begin
let s =
try List.assq r !m
with Not_found ->
let s = "X" ^ string_of_int !n in
incr n;
m := (r,s)::!m;
s
in
Fmt.fprintf f "%s%s" s
(if vardepth=0 then "" else "^" ^ string_of_int vardepth)
end else if nice then begin
aux prec depth f (!do_deref ~from:vardepth ~to_:depth args !!r)
end else Fmt.fprintf f "<%a>_%d" (aux min_prec vardepth) !!r vardepth
and pp_arg prec depth f n =
let name= try List.nth names n with Failure _ -> "A" ^ string_of_int n in
if try env.(n) == C.dummy with Invalid_argument _ -> true then
Fmt.fprintf f "%s" name
else if nice then begin
if argsdepth <= depth then
let dereffed = !do_deref ~from:argsdepth ~to_:depth 0 env.(n) in
aux prec depth f dereffed
else
(* The instantiated Args live at an higher depth, and that's ok.
But if we try to deref we make an imperative mess *)
Fmt.fprintf f "≪%a≫_%d" (aux min_prec argsdepth) env.(n) argsdepth
end else Fmt.fprintf f "≪%a≫_%d" (aux min_prec argsdepth) env.(n) argsdepth
(* ::(a, ::(b, nil)) --> [a,b] *)
and flat_cons_to_list depth acc t = match t with
UVar (r,vardepth,terms) when !!r != C.dummy ->
flat_cons_to_list depth acc
(!do_deref ~from:vardepth ~to_:depth terms !!r)
| AppUVar (r,vardepth,terms) when !!r != C.dummy ->
flat_cons_to_list depth acc
(!do_app_deref ~from:vardepth ~to_:depth terms !!r)
| Cons (x,y) -> flat_cons_to_list depth (x::acc) y
| _ -> List.rev acc, t
and is_lambda depth =
function
Lam _ -> true
| UVar (r,vardepth,terms) when !!r != C.dummy ->
is_lambda depth (!do_deref ~from:vardepth ~to_:depth terms !!r)
| AppUVar (r,vardepth,terms) when !!r != C.dummy ->
is_lambda depth (!do_app_deref ~from:vardepth ~to_:depth terms !!r)
| _ -> false
and aux_last prec depth f t =
if nice then begin
match t with
Lam _ -> aux min_prec depth f t
| UVar (r,vardepth,terms) when !!r != C.dummy ->
aux_last prec depth f (!do_deref ~from:vardepth ~to_:depth terms !!r)
| AppUVar (r,vardepth,terms) when !!r != C.dummy ->
aux_last prec depth f
(!do_app_deref ~from:vardepth ~to_:depth terms !!r)
| _ -> aux prec depth f t
end else aux inf_prec depth f t
and aux prec depth f t =
let with_parens ?(test=true) myprec h =
if test && myprec < prec then
(Fmt.fprintf f "(" ; h () ; Fmt.fprintf f ")")
else h () in
match t with
| (Cons _ | Nil) ->
let prefix,last = flat_cons_to_list depth [] t in
Fmt.fprintf f "[" ;
pplist ~boxed:true (aux Elpi_parser.list_element_prec depth) "," f prefix ;
if last != Nil then begin
Fmt.fprintf f " | " ;
aux prec 1 f last
end;
Fmt.fprintf f "]"
| Const s -> ppconstant f s
| App (hd,x,xs) ->
(try
let assoc,hdlvl =
Elpi_parser.precedence_of (F.from_string (C.show hd)) in
with_parens hdlvl
(fun _ -> match assoc with
Elpi_parser.Infix when List.length xs = 1 ->
Fmt.fprintf f "@[<hov 1>%a@ %a@ %a@]"
(aux (hdlvl+1) depth) x ppconstant hd
(aux (hdlvl+1) depth) (List.hd xs)
| Elpi_parser.Infixl when List.length xs = 1 ->
Fmt.fprintf f "@[<hov 1>%a@ %a@ %a@]"
(aux hdlvl depth) x ppconstant hd
(aux (hdlvl+1) depth) (List.hd xs)
| Elpi_parser.Infixr when List.length xs = 1 ->
Fmt.fprintf f "@[<hov 1>%a@ %a@ %a@]"
(aux (hdlvl+1) depth) x ppconstant hd
(aux hdlvl depth) (List.hd xs)
| Elpi_parser.Prefix when xs = [] ->
Fmt.fprintf f "@[<hov 1>%a@ %a@]" ppconstant hd
(aux hdlvl depth) x
| Elpi_parser.Postfix when xs = [] ->
Fmt.fprintf f "@[<hov 1>%a@ %a@]" (aux hdlvl depth) x
ppconstant hd
| _ ->
pp_app f ppconstant (aux inf_prec depth)
~pplastarg:(aux_last inf_prec depth) (hd,x::xs))
with Not_found ->
let lastarg = List.nth (x::xs) (List.length xs) in
let hdlvl =
if is_lambda depth lastarg then lam_prec
else if hd == C.andc then 110
else appl_prec in
with_parens hdlvl (fun _ ->
if hd == C.andc then
pplist (aux inf_prec depth) ~pplastelem:(aux_last inf_prec depth) "," f (x::xs)
else pp_app f ppconstant (aux inf_prec depth)
~pplastarg:(aux_last inf_prec depth) (hd,x::xs)))
| Custom (hd,xs) ->
with_parens appl_prec (fun _ ->
pp_app f ppconstant (aux inf_prec depth)
~pplastarg:(aux_last inf_prec depth) (hd,xs))
| UVar (r,vardepth,argsno) when not nice ->
let args = List.map destConst (C.mkinterval vardepth argsno 0) in
with_parens ~test:(args <> []) appl_prec (fun _ ->
Fmt.fprintf f "." ;
pp_app f (pp_uvar inf_prec depth vardepth 0) ppconstant (r,args))
| UVar (r,vardepth,argsno) when !!r == C.dummy ->
let diff = vardepth - depth0 in
let diff = if diff >= 0 then diff else 0 in
let vardepth = vardepth - diff in
let argsno = argsno + diff in
let args = List.map destConst (C.mkinterval vardepth argsno 0) in
with_parens ~test:(args <> []) appl_prec (fun _ ->
pp_app f (pp_uvar inf_prec depth vardepth 0) ppconstant (r,args))
| UVar (r,vardepth,argsno) ->
pp_uvar prec depth vardepth argsno f r
| AppUVar (r,vardepth,terms) when !!r != C.dummy && nice ->
aux prec depth f (!do_app_deref ~from:vardepth ~to_:depth terms !!r)
| AppUVar (r,vardepth,terms) ->
with_parens appl_prec (fun _ ->
pp_app f (pp_uvar inf_prec depth vardepth 0) (aux inf_prec depth)
~pplastarg:(aux_last inf_prec depth) (r,terms))
| Arg (n,argsno) ->
let args = List.map destConst (C.mkinterval argsdepth argsno 0) in
with_parens ~test:(args <> []) appl_prec (fun _ ->
pp_app f (pp_arg prec depth) ppconstant (n,args))
| AppArg (v,terms) ->
with_parens appl_prec (fun _ ->
pp_app f (pp_arg inf_prec depth) (aux inf_prec depth)
~pplastarg:(aux_last inf_prec depth) (v,terms))
| Lam t ->
with_parens lam_prec (fun _ ->
let c = C.of_dbl depth in
Fmt.fprintf f "%a \\@ %a" (aux inf_prec depth) c
(aux min_prec (depth+1)) t)
| CData d -> CData.pp f d
in
try aux min_prec depth0 f t with e -> Fmt.fprintf f "EXN PRINTING: %s" (Printexc.to_string e)
;;
let ppterm = xppterm ~nice:false
let uppterm = xppterm ~nice:true
let () = extend_printer pp_oref (fun fmt (id,t) ->
if not (UUID.equal id id_term) then `Passed
else
let t : term = Obj.obj t in
if t == C.dummy then Fmt.fprintf fmt "_"
else uppterm 0 [] 0 empty_env fmt t;
`Printed)
end (* }}} *)
open Pp
module CHR : sig
(* a set of rules *)
type t
(* a set of predicates contributing to represent a constraint *)
type clique
type rule = (term, int) Elpi_ast.chr
val empty : t
val new_clique : constant list -> t -> t * clique
val clique_of : constant -> t -> C.Set.t
val add_rule : clique -> rule -> t -> t
val rules_for : constant -> t -> rule list
(* to store CHR.t in program *)
val wrap_chr : t -> chr
val unwrap_chr : chr -> t
end = struct (* {{{ *)
type rule = (term, int) Elpi_ast.chr
type t = { cliques : C.Set.t C.Map.t; rules : rule list C.Map.t }
type clique = C.Set.t
type chr += Chr of t
let () = extend_printer pp_chr (fun fmt -> function
| Chr c -> Fmt.fprintf fmt "<CHRs>";`Printed
| _ -> `Passed)
let wrap_chr x = Chr x
let unwrap_chr = function Chr x -> x | _ -> assert false
let empty = { cliques = C.Map.empty; rules = C.Map.empty }
let new_clique cl ({ cliques } as chr) =
if cl = [] then error "empty clique";
let c = List.fold_right C.Set.add cl C.Set.empty in
if C.Map.exists (fun _ c' -> not (C.Set.is_empty (C.Set.inter c c'))) cliques then
error "overlapping constraint cliques";
let cliques =
List.fold_right (fun x cliques -> C.Map.add x c cliques) cl cliques in
{ chr with cliques }, c
let clique_of c { cliques } =
try C.Map.find c cliques with Not_found -> C.Set.empty
let add_rule cl r ({ rules } as chr) =
let rules = C.Set.fold (fun c rules ->
try
let rs = C.Map.find c rules in
C.Map.add c (rs @ [r]) rules
with Not_found -> C.Map.add c [r] rules)
cl rules in
{ chr with rules }
let rules_for c { rules } =
try C.Map.find c rules
with Not_found -> []
end (* }}} *)
module CustomConstraints : sig
type 'a constraint_type
(* Must be purely functional *)
val declare_constraint :
name:string ->
pp:(Fmt.formatter -> 'a -> unit) ->
empty:'a ->
'a constraint_type
type state = Obj.t IM.t
val update : state ref -> 'a constraint_type -> ('a -> 'a) -> unit
val read : state ref -> 'a constraint_type -> 'a
end = struct
type 'a constraint_type = int
type state = Obj.t IM.t
let custom_constraints_declarations = ref IM.empty
let cid = ref 0
let declare_constraint ~name ~pp ~empty =
incr cid;
custom_constraints_declarations :=
IM.add !cid (name,Obj.repr pp, Obj.repr empty) !custom_constraints_declarations;
!cid
let find custom_constraints id =
try IM.find id !custom_constraints
with Not_found ->
let _, _, init = IM.find id !custom_constraints_declarations in
init
let update custom_constraints id f =
custom_constraints :=
IM.add id (Obj.repr (f (Obj.obj (find custom_constraints id)))) !custom_constraints
let read custom_constraints id = Obj.obj (find custom_constraints id)
end
(* true=input, false=output *)
type mode = bool list [@@deriving show]
module TwoMapIndexingTypes = struct (* {{{ *)
type key1 = int
type key2 = int
type key = key1 * key2
type clause = {
depth : int;
args : term list;
hyps : term list;
vars : int;
key : key;
mode: mode;
}
type idx = {
src : (int * term) list;
map : (clause list * clause list * clause list Elpi_ptmap.t) Elpi_ptmap.t
}
end (* }}} *)
module UnifBitsTypes = struct (* {{{ *)
type key = int
type clause = {
depth : int;
args : term list;
hyps : term list;
vars : int;
key : key;
mode: mode;
}
type idx = {
src : (int * term) list;
map : (clause * int) list Elpi_ptmap.t (* timestamp *)
}
end (* }}} *)
type idx = TwoMapIndexingTypes.idx
type key = TwoMapIndexingTypes.key
type clause = TwoMapIndexingTypes.clause = {
depth : int;
args : term list;
hyps : term list;
vars : int;
key : key;
mode : mode;
}
type mode_decl =
| Mono of mode
| Multi of (constant * (constant * constant) list) list
(* An elpi program, as parsed. But for idx and query_depth that are threaded
around in the main loop, chr and modes are globally stored in Constraints
and Clausify. *)
type clause_w_info = {
clloc : CData.t;
clargsname : string list;
clbody : clause;
}
let drop_clause_info { clbody } = clbody
type program = {
(* n of sigma/local-introduced variables *)
query_depth : int;
(* the lambda-Prolog program: an indexed list of clauses *)
prolog_program : prolog_prog [@printer (pp_extensible pp_prolog_prog)];
(* constraint handling rules *)
chr : chr [@printer (pp_extensible pp_chr)];
modes : mode_decl C.Map.t;
(* extra stuff, for typing & pretty printing *)
declared_types : (constant * int * term) list; (* name, nARGS, type *)
clauses_w_info : clause_w_info list
}
type query = Ploc.t * string list * int * env * term
type prolog_prog += Index of idx
let () = extend_printer pp_prolog_prog (fun fmt -> function
| Index _ -> Fmt.fprintf fmt "<prolog_prog>";`Printed
| _ -> `Passed)
let wrap_prolog_prog x = Index x
let unwrap_prolog_prog = function Index x -> x | _ -> assert false
exception No_clause
(* vim: set foldmethod=marker: *)