Skip to content

Commit da123f6

Browse files
committed
tabling: adapt stack/choice
1 parent de677d1 commit da123f6

File tree

2 files changed

+82
-57
lines changed

2 files changed

+82
-57
lines changed

src/runtime.ml

Lines changed: 72 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,29 +2741,37 @@ let repack_goal (gid[@trace]) ~depth program goal =
27412741
{ depth ; program ; goal ; gid = gid [@trace] }
27422742
[@@inline]
27432743

2744-
2745-
(* The activation frames points to the choice point that
2746-
cut should backtrack to, i.e. the first one not to be
2747-
removed. We call it catto_alts in the code. *)
2748-
type frame =
2749-
| FNil
2750-
| FCons of (*lvl:*)alternative * goal list * frame
2751-
and alternative = {
2752-
cutto_alts : alternative;
2753-
program : prolog_prog;
2754-
adepth : int;
2755-
agoal_hd : constant;
2756-
ogoal_arg : term;
2757-
ogoal_args : term list;
2758-
agid : UUID.t; [@trace]
2759-
goals : goal list;
2760-
stack : frame;
2761-
trail : T.trail;
2762-
state : State.t;
2763-
clauses : clause list;
2764-
next : alternative;
2744+
type goals_crumbles = {
2745+
predicate : constant;
2746+
fst_arg : term;
2747+
other_args : term list;
2748+
brothers : goal list;
27652749
}
2766-
let noalts : alternative = Obj.magic 0
2750+
2751+
(* The tree *)
2752+
type continuation = (* the AND part, what to do next *)
2753+
| Done
2754+
| ExitSLGRoot of { heap : unit; next : continuation; alts : alternative }
2755+
| TableSolution of unit
2756+
| SolveGoals of { cutto_alts : alternative; brothers : goal list; next : continuation }
2757+
and alternative = (* the OR part, what to do if we fail *)
2758+
| Noalts
2759+
| UnblockSLGGenerator of slg_generator (* a branch of the tree that could have been cut *)
2760+
| ExploreAnotherSLDPath of {
2761+
program : prolog_prog;
2762+
adepth : int;
2763+
path : goals_crumbles;
2764+
agid : UUID.t; [@trace]
2765+
stack : continuation;
2766+
trail : T.trail;
2767+
state : State.t;
2768+
clauses : clause list;
2769+
alts : alternative;
2770+
cutto_alts : alternative;
2771+
}
2772+
and slg_generator =
2773+
| Root of { root_goal : term; root_goal_args : int; clauses : clause list; }
2774+
| UnexploredBranches of { heap : unit; alts : alternative }
27672775

27682776
(******************************************************************************
27692777
Constraint propagation
@@ -3333,7 +3341,7 @@ let pp_candidate ~depth ~k fmt ({ loc } as cl) =
33333341
let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x executable -> 'x runtime =
33343342
(* Input to be read as the orl (((p,g)::gs)::next)::alts
33353343
depth >= 0 is the number of variables in the context. *)
3336-
let rec run depth p g (gid[@trace]) gs (next : frame) alts cutto_alts =
3344+
let rec run depth p g (gid[@trace]) gs (next : continuation) alts cutto_alts =
33373345
[%cur_pred (pred_of g)];
33383346
[%trace "run" ~rid begin
33393347

@@ -3405,11 +3413,11 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
34053413
| Const k -> [%spy "user:rule" ~rid ~gid pp_string "backchain"];
34063414
let clauses = get_clauses depth k g p in
34073415
[%spyl "user:candidates" ~rid ~gid (pp_candidate ~depth ~k) clauses];
3408-
[%tcall backchain depth p (k, C.dummy, [], gs) (gid[@trace]) next alts cutto_alts clauses]
3416+
[%tcall backchain depth p { predicate = k; fst_arg = C.dummy; other_args = []; brothers = gs} (gid[@trace]) next alts cutto_alts clauses]
34093417
| App (k,x,xs) -> [%spy "user:rule" ~rid ~gid pp_string "backchain"];
34103418
let clauses = get_clauses depth k g p in
34113419
[%spyl "user:candidates" ~rid ~gid (pp_candidate ~depth ~k) clauses];
3412-
[%tcall backchain depth p (k, x, xs, gs) (gid[@trace]) next alts cutto_alts clauses]
3420+
[%tcall backchain depth p { predicate = k; fst_arg = x; other_args = xs; brothers = gs} (gid[@trace]) next alts cutto_alts clauses]
34133421
| Builtin(c, args) -> [%spy "user:rule" ~rid ~gid pp_string "builtin"];
34143422
begin match Constraints.exect_builtin_predicate c ~depth p (gid[@trace]) args with
34153423
| gs' ->
@@ -3428,15 +3436,15 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
34283436
error "The goal is a flexible term"
34293437
end]
34303438

3431-
(* We pack some arguments into a tuple otherwise we consume too much stack *)
3432-
and backchain depth p (k, arg, args_of_g, gs) (gid[@trace]) next alts cutto_alts cp = [%trace "select" ~rid begin
3439+
(* We pack some arguments into the goals_crumbles record otherwise we consume too much stack *)
3440+
and backchain depth p ({ predicate = k; fst_arg = arg; other_args = args_of_g; brothers = gs} as g_gs) (gid[@trace]) next alts cutto_alts cp = [%trace "select" ~rid begin
34333441
match cp with
34343442
| [] -> [%spy "user:select" ~rid ~gid pp_string "fail"];
34353443
[%tcall next_alt alts]
34363444
| { depth = c_depth; mode = c_mode; args = c_args; hyps = c_hyps; vars = c_vars; loc } :: cs ->
34373445
[%spy "user:select" ~rid ~gid (pp_option Util.CData.pp) (Util.option_map Ast.cloc.Util.CData.cin loc) (ppclause ~depth ~hd:k) { depth = c_depth; mode = c_mode; args = c_args; hyps = c_hyps; vars = c_vars; loc }];
34383446
let old_trail = !T.trail in
3439-
T.last_call := alts == noalts && cs == [];
3447+
T.last_call := alts == Noalts && cs == [];
34403448
let env = Array.make c_vars C.dummy in
34413449
match
34423450
match c_args with
@@ -3446,21 +3454,21 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
34463454
| [] -> unif ~argsdepth:depth ~matching:false (gid[@trace]) depth env c_depth arg x && for_all23 ~argsdepth:depth (unif (gid[@trace])) depth env c_depth args_of_g xs
34473455
| matching :: ms -> unif ~argsdepth:depth ~matching (gid[@trace]) depth env c_depth arg x && for_all3b3 ~argsdepth:depth (unif (gid[@trace])) depth env c_depth args_of_g xs ms false
34483456
with
3449-
| false -> T.undo old_trail (); [%tcall backchain depth p (k, arg, args_of_g, gs) (gid[@trace]) next alts cutto_alts cs]
3457+
| false -> T.undo old_trail (); [%tcall backchain depth p g_gs (gid[@trace]) next alts cutto_alts cs]
34503458
| true ->
34513459
let oldalts = alts in
34523460
let alts = if cs = [] then alts else
3453-
{ program = p; adepth = depth; agoal_hd = k; ogoal_arg = arg; ogoal_args = args_of_g; agid = gid[@trace]; goals = gs; stack = next;
3461+
ExploreAnotherSLDPath { program = p; adepth = depth; path = g_gs; agid = gid[@trace]; stack = next;
34543462
trail = old_trail;
34553463
state = !CS.state;
3456-
clauses = cs; cutto_alts = cutto_alts ; next = alts} in
3464+
clauses = cs; cutto_alts = cutto_alts ; alts} in
34573465
begin match c_hyps with
34583466
| [] ->
34593467
begin match gs with
34603468
| [] -> [%tcall pop_andl alts next cutto_alts]
34613469
| { depth ; program; goal; gid = gid [@trace] } :: gs -> [%tcall run depth program goal (gid[@trace]) gs next alts cutto_alts] end
34623470
| h::hs ->
3463-
let next = if gs = [] then next else FCons (cutto_alts,gs,next) in
3471+
let next = if gs = [] then next else SolveGoals { cutto_alts; brothers = gs; next } in
34643472
let h = move ~argsdepth:depth ~from:c_depth ~to_:depth env h in
34653473
let hs =
34663474
List.map (fun x->
@@ -3472,14 +3480,18 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
34723480

34733481
and cut (gid[@trace]) gs next (alts[@trace]) cutto_alts =
34743482
[%spy "user:cut" ~rid ~gid (fun fmt alts ->
3475-
let rec prune ({ agid = agid[@trace]; clauses; adepth = depth; agoal_hd = hd } as alts) =
3476-
if alts != cutto_alts then begin
3477-
Format.fprintf fmt "%a" (pplist (ppclause ~depth ~hd) " | ") clauses;
3478-
prune alts.next
3479-
end in
3483+
let rec prune alts =
3484+
if alts = cutto_alts then () else
3485+
match alts with
3486+
| ExploreAnotherSLDPath ({ agid = agid[@trace]; clauses; adepth = depth; path = { predicate = hd } } as alts) ->
3487+
Format.fprintf fmt "%a" (pplist (ppclause ~depth ~hd) " | ") clauses;
3488+
prune alts.alts
3489+
| Noalts -> ()
3490+
| UnblockSLGGenerator _ -> ()
3491+
in
34803492
prune alts
34813493
) alts];
3482-
if cutto_alts == noalts then T.trail := T.empty ();
3494+
if cutto_alts == Noalts then T.trail := T.empty ();
34833495
match gs with
34843496
| [] -> pop_andl cutto_alts next cutto_alts
34853497
| { depth; program; goal; gid = gid [@trace] } :: gs -> run depth program goal (gid[@trace]) gs next cutto_alts cutto_alts
@@ -3510,7 +3522,7 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
35103522
let sol = copy g in
35113523
[%spy "findall solution:" ~rid ~gid (ppterm depth [] ~argsdepth:0 empty_env) g];
35123524
solutions := sol :: !solutions in
3513-
let alternatives = ref noalts in
3525+
let alternatives = ref Noalts in
35143526
try
35153527
alternatives := search ();
35163528
add_sol ();
@@ -3533,18 +3545,20 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
35333545

35343546
and pop_andl alts next cutto_alts =
35353547
match next with
3536-
| FNil ->
3548+
| Done ->
35373549
(match resume_all () with
35383550
None ->
35393551
Fmt.fprintf Fmt.std_formatter
35403552
"Undo triggered by goal resumption\n%!";
35413553
[%tcall next_alt alts]
35423554
| Some ({ depth; program; goal; gid = gid [@trace] } :: gs) ->
3543-
run depth program goal (gid[@trace]) gs FNil alts cutto_alts
3555+
run depth program goal (gid[@trace]) gs Done alts cutto_alts
35443556
| Some [] -> alts)
3545-
| FCons (_,[],_) -> anomaly "empty stack frame"
3546-
| FCons(cutto_alts, { depth; program; goal; gid = gid [@trace] } :: gs, next) ->
3557+
| SolveGoals { brothers = []; _ } -> anomaly "empty continuation"
3558+
| SolveGoals { cutto_alts; brothers = { depth; program; goal; gid = gid [@trace] } :: gs; next } ->
35473559
run depth program goal (gid[@trace]) gs next alts cutto_alts
3560+
| ExitSLGRoot _ -> assert false
3561+
| TableSolution _ -> assert false
35483562

35493563
and resume_all () : goal list option =
35503564
(* if fm then Some [] else *)
@@ -3584,13 +3598,14 @@ end;*)
35843598
else None
35853599

35863600
and next_alt alts =
3587-
if alts == noalts then raise No_clause
3588-
else
3589-
let { program = p; clauses; agoal_hd = k; ogoal_arg = arg; ogoal_args = args; agid = gid [@trace]; goals = gs; stack = next;
3590-
trail = old_trail; state = old_state;
3591-
adepth = depth; cutto_alts = cutto_alts; next = alts} = alts in
3592-
T.undo ~old_trail ~old_state ();
3593-
backchain depth p (k, arg, args, gs) (gid[@trace]) next alts cutto_alts clauses
3601+
match alts with
3602+
| ExploreAnotherSLDPath { program = p; clauses; path; agid = gid [@trace]; stack = next;
3603+
trail = old_trail; state = old_state;
3604+
adepth = depth; cutto_alts = cutto_alts; alts} ->
3605+
T.undo ~old_trail ~old_state ();
3606+
backchain depth p path (gid[@trace]) next alts cutto_alts clauses
3607+
| UnblockSLGGenerator _ -> assert false
3608+
| Noalts -> raise No_clause
35943609
in
35953610

35963611
(* Finally the runtime *)
@@ -3622,7 +3637,7 @@ end;*)
36223637
let search = exec (fun () ->
36233638
[%spy "dev:trail:init" ~rid (fun fmt () -> T.print_trail fmt) ()];
36243639
set T.trail (T.empty ());
3625-
run initial_depth !orig_prolog_program initial_goal ((UUID.make ())[@trace]) [] FNil noalts noalts) in
3640+
run initial_depth !orig_prolog_program initial_goal ((UUID.make ())[@trace]) [] Done Noalts Noalts) in
36263641
let destroy () = () in
36273642
let next_solution = exec next_alt in
36283643
incr max_runtime_id;
@@ -3651,8 +3666,8 @@ let mk_outcome search get_cs assignments =
36513666
} in
36523667
Success solution, alts
36533668
with
3654-
| No_clause (*| Non_linear*) -> Failure, noalts
3655-
| No_more_steps -> NoMoreSteps, noalts
3669+
| No_clause (*| Non_linear*) -> Failure, Noalts
3670+
| No_more_steps -> NoMoreSteps, Noalts
36563671

36573672
let execute_once ?max_steps ?delay_outside_fragment exec =
36583673
auxsg := [];
@@ -3662,18 +3677,18 @@ let execute_once ?max_steps ?delay_outside_fragment exec =
36623677

36633678
let execute_loop ?delay_outside_fragment exec ~more ~pp =
36643679
let { search; next_solution; get } = make_runtime ?delay_outside_fragment exec in
3665-
let k = ref noalts in
3680+
let k = ref Noalts in
36663681
let do_with_infos f =
36673682
let time0 = Unix.gettimeofday() in
36683683
let o, alts = mk_outcome f (fun () -> get CS.Ugly.delayed, get CS.state |> State.end_execution, exec.query_arguments, { Data.uv_names = ref (get Pp.uv_names); table = get C.table }) exec.assignments in
36693684
let time1 = Unix.gettimeofday() in
36703685
k := alts;
36713686
pp (time1 -. time0) o in
36723687
do_with_infos search;
3673-
while !k != noalts do
3674-
if not(more()) then k := noalts else
3688+
while !k != Noalts do
3689+
if not(more()) then k := Noalts else
36753690
try do_with_infos (fun () -> next_solution !k)
3676-
with No_clause -> pp 0.0 Failure; k := noalts
3691+
with No_clause -> pp 0.0 Failure; k := Noalts
36773692
done
36783693
;;
36793694

trace/ppx/trace_ppx.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ let map_trace = object(self)
146146
let lbls = lbls |> List.filter (fun { pld_attributes = l; _ } ->
147147
not (has_iftrace_attribute l)) in
148148
{ tyd with ptype_kind = Ptype_record lbls }
149+
| Ptype_variant l ->
150+
let aux ({ pcd_args; _ } as pcd) =
151+
match pcd_args with
152+
| Pcstr_record lbls when not !enabled ->
153+
let lbls = lbls |> List.filter (fun { pld_attributes = l; _ } ->
154+
not (has_iftrace_attribute l)) in
155+
{pcd with pcd_args = Pcstr_record lbls }
156+
| _ -> pcd in
157+
let l = List.map aux l in
158+
{ tyd with ptype_kind = Ptype_variant l }
149159
| _ -> tyd
150160

151161
method! expression e =

0 commit comments

Comments
 (0)