Skip to content

Commit ee2d786

Browse files
committed
tabling: adapt stack/choice
1 parent e5629a3 commit ee2d786

File tree

2 files changed

+92
-69
lines changed

2 files changed

+92
-69
lines changed

src/runtime.ml

Lines changed: 82 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,29 +3014,37 @@ let repack_goal (gid[@trace]) ~depth program goal =
30143014
{ depth ; program ; goal ; gid = gid [@trace] }
30153015
[@@inline]
30163016

3017-
3018-
(* The activation frames points to the choice point that
3019-
cut should backtrack to, i.e. the first one not to be
3020-
removed. We call it catto_alts in the code. *)
3021-
type frame =
3022-
| FNil
3023-
| FCons of (*lvl:*)alternative * goal list * frame
3024-
and alternative = {
3025-
cutto_alts : alternative;
3026-
program : prolog_prog;
3027-
adepth : int;
3028-
agoal_hd : constant;
3029-
ogoal_arg : term;
3030-
ogoal_args : term list;
3031-
agid : UUID.t; [@trace]
3032-
goals : goal list;
3033-
stack : frame;
3034-
trail : T.trail;
3035-
state : State.t;
3036-
clauses : clause list;
3037-
next : alternative;
3017+
type goals_crumbles = {
3018+
predicate : constant;
3019+
fst_arg : term;
3020+
other_args : term list;
3021+
brothers : goal list;
30383022
}
3039-
let noalts : alternative = Obj.magic (Sys.opaque_identity 0)
3023+
3024+
(* The tree *)
3025+
type continuation = (* the AND part, what to do next *)
3026+
| Done
3027+
| ExitSLGRoot of { heap : unit; next : continuation; alts : alternative }
3028+
| TableSolution of unit
3029+
| SolveGoals of { cutto_alts : alternative; brothers : goal list; next : continuation }
3030+
and alternative = (* the OR part, what to do if we fail *)
3031+
| Noalts
3032+
| UnblockSLGGenerator of slg_generator (* a branch of the tree that could have been cut *)
3033+
| ExploreAnotherSLDPath of {
3034+
program : prolog_prog;
3035+
adepth : int;
3036+
path : goals_crumbles;
3037+
agid : UUID.t; [@trace]
3038+
stack : continuation;
3039+
trail : T.trail;
3040+
state : State.t;
3041+
clauses : clause list;
3042+
alts : alternative;
3043+
cutto_alts : alternative;
3044+
}
3045+
and slg_generator =
3046+
| Root of { root_goal : term; root_goal_args : int; clauses : clause list; }
3047+
| UnexploredBranches of { heap : unit; alts : alternative }
30403048

30413049
(******************************************************************************
30423050
Constraint propagation
@@ -3719,7 +3727,7 @@ let pp_CHR_resumed_goal { depth; program; goal; gid = gid[@trace] } =
37193727
let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x executable -> 'x runtime =
37203728
(* Input to be read as the orl (((p,g)::gs)::next)::alts
37213729
depth >= 0 is the number of variables in the context. *)
3722-
let rec run depth p g (gid[@trace]) gs (next : frame) alts cutto_alts =
3730+
let rec run depth p g (gid[@trace]) gs (next : continuation) alts cutto_alts =
37233731
[%cur_pred (pred_of g)];
37243732
[%trace "run" ~rid begin
37253733

@@ -3804,17 +3812,17 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
38043812
let clauses = get_clauses ~depth k g p in
38053813
[%spy "user:rule" ~rid ~gid pp_string "backchain"];
38063814
[%spyl "user:rule:backchain:candidates" ~rid ~gid (pp_candidate ~depth ~k) clauses];
3807-
[%tcall backchain depth p (k, C.dummy, [], gs) (gid[@trace]) next alts cutto_alts clauses]
3815+
[%tcall backchain depth p { predicate = k; fst_arg = C.dummy; other_args = []; brothers = gs} (gid[@trace]) next alts cutto_alts clauses]
38083816
| App (k,x,xs) ->
38093817
let clauses = get_clauses ~depth k g p in
38103818
[%spy "user:rule" ~rid ~gid pp_string "backchain"];
38113819
[%spyl "user:rule:backchain:candidates" ~rid ~gid (pp_candidate ~depth ~k) clauses];
3812-
[%tcall backchain depth p (k, x, xs, gs) (gid[@trace]) next alts cutto_alts clauses]
3820+
[%tcall backchain depth p { predicate = k; fst_arg = x; other_args = xs; brothers = gs} (gid[@trace]) next alts cutto_alts clauses]
38133821
| Builtin(c, args) -> [%spy "user:rule" ~rid ~gid pp_string "builtin"]; [%spy "user:rule:builtin:name" ~rid ~gid pp_string (C.show c)];
38143822
let once ~depth g state =
38153823
CS.state := state;
38163824
let { depth; program; goal; gid = gid [@trace] } = (make_subgoal[@inlined]) (gid[@trace]) ~depth p g in
3817-
let _alts = run depth program goal (gid[@trace]) [] FNil noalts noalts in
3825+
let _alts = run depth program goal (gid[@trace]) [] Done Noalts Noalts in
38183826
!CS.state in
38193827
begin match Constraints.exect_builtin_predicate ~once c ~depth p (gid[@trace]) args with
38203828
| gs' ->
@@ -3833,15 +3841,15 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
38333841
error "The goal is a flexible term"
38343842
end]
38353843

3836-
(* We pack some arguments into a tuple otherwise we consume too much stack *)
3837-
and backchain depth p (k, arg, args_of_g, gs) (gid[@trace]) next alts cutto_alts cp = [%trace "select" ~rid begin
3844+
(* We pack some arguments into the goals_crumbles record otherwise we consume too much stack *)
3845+
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
38383846
match cp with
38393847
| [] -> [%spy "user:rule:backchain" ~rid ~gid pp_string "fail"];
38403848
[%tcall next_alt alts]
38413849
| { depth = c_depth; mode = c_mode; args = c_args; hyps = c_hyps; vars = c_vars; loc } :: cs ->
38423850
[%spy "user:rule:backchain:try" ~rid ~gid (pp_option Util.CData.pp) (Util.option_map Ast.cloc.Util.CData.cin loc) (ppclause ~hd:k) { depth = c_depth; mode = c_mode; args = c_args; hyps = c_hyps; vars = c_vars; loc }];
38433851
let old_trail = !T.trail in
3844-
T.last_call := alts == noalts && cs == [];
3852+
T.last_call := alts == Noalts && cs == [];
38453853
let env = Array.make c_vars C.dummy in
38463854
match
38473855
match c_args with
@@ -3851,23 +3859,22 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
38513859
| [] -> 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
38523860
| arg_mode :: ms -> unif ~argsdepth:depth ~matching:(arg_mode == Input) (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
38533861
with
3854-
| false ->
3855-
T.undo ~old_trail (); [%tcall backchain depth p (k, arg, args_of_g, gs) (gid[@trace]) next alts cutto_alts cs]
3862+
| false -> T.undo old_trail (); [%tcall backchain depth p g_gs (gid[@trace]) next alts cutto_alts cs]
38563863
| true ->
38573864
let oldalts = alts in
38583865
let alts = if cs = [] then alts else
3859-
{ program = p; adepth = depth; agoal_hd = k; ogoal_arg = arg; ogoal_args = args_of_g; agid = gid[@trace]; goals = gs; stack = next;
3866+
ExploreAnotherSLDPath { program = p; adepth = depth; path = g_gs; agid = gid[@trace]; stack = next;
38603867
trail = old_trail;
38613868
state = !CS.state;
3862-
clauses = cs; cutto_alts = cutto_alts ; next = alts} in
3869+
clauses = cs; cutto_alts = cutto_alts ; alts} in
38633870
begin match c_hyps with
38643871
| [] ->
38653872
[%spy "user:rule:backchain" ~rid ~gid pp_string "success"];
38663873
begin match gs with
38673874
| [] -> [%tcall pop_andl alts next cutto_alts]
38683875
| { depth ; program; goal; gid = gid [@trace] } :: gs -> [%tcall run depth program goal (gid[@trace]) gs next alts cutto_alts] end
38693876
| h::hs ->
3870-
let next = if gs = [] then next else FCons (cutto_alts,gs,next) in
3877+
let next = if gs = [] then next else SolveGoals { cutto_alts; brothers = gs; next } in
38713878
let h = move ~argsdepth:depth ~from:c_depth ~to_:depth env h in
38723879
let gid[@trace] = make_subgoal_id gid ((depth,h)[@trace]) in
38733880
let hs =
@@ -3881,15 +3888,19 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
38813888
and cut (gid[@trace]) gs next (alts[@trace]) cutto_alts =
38823889
[%spy "user:rule" ~rid ~gid pp_string "cut"];
38833890
let ()[@trace] =
3884-
let rec prune ({ agid = agid[@trace]; clauses; adepth = depth; agoal_hd = hd } as alts) =
3885-
if alts != cutto_alts then begin
3886-
List.iter (fun c ->
3887-
[%spy "user:rule:cut:branch" ~rid UUID.pp agid (pp_option Util.CData.pp) (Util.option_map Ast.cloc.Util.CData.cin c.loc) (ppclause ~hd) c])
3888-
clauses;
3889-
prune alts.next
3890-
end in
3891+
let rec prune alts =
3892+
if alts == cutto_alts then () else
3893+
match alts with
3894+
| ExploreAnotherSLDPath ({ agid = agid[@trace]; clauses; adepth = depth; path = { predicate = hd } } as alts) ->
3895+
List.iter (fun c ->
3896+
[%spy "user:rule:cut:branch" ~rid UUID.pp agid (pp_option Util.CData.pp) (Util.option_map Ast.cloc.Util.CData.cin c.loc) (ppclause ~hd) c])
3897+
clauses;
3898+
prune alts.alts
3899+
| Noalts -> ()
3900+
| UnblockSLGGenerator _ -> ()
3901+
in
38913902
prune alts in
3892-
if cutto_alts == noalts then T.trail := T.empty ();
3903+
if cutto_alts == Noalts then T.trail := T.empty ();
38933904
match gs with
38943905
| [] -> pop_andl cutto_alts next cutto_alts
38953906
| { depth; program; goal; gid = gid [@trace] } :: gs -> run depth program goal (gid[@trace]) gs next cutto_alts cutto_alts
@@ -3921,7 +3932,7 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
39213932
let sol = copy g in
39223933
[%spy "findall solution:" ~rid ~gid (ppterm depth [] ~argsdepth:0 empty_env) g];
39233934
solutions := sol :: !solutions in
3924-
let alternatives = ref noalts in
3935+
let alternatives = ref Noalts in
39253936
try
39263937
alternatives := search ();
39273938
add_sol ();
@@ -3947,18 +3958,20 @@ let make_runtime : ?max_steps: int -> ?delay_outside_fragment: bool -> 'x execut
39473958

39483959
and pop_andl alts next cutto_alts =
39493960
match next with
3950-
| FNil ->
3961+
| Done ->
39513962
(match resume_all () with
39523963
None ->
39533964
Fmt.fprintf Fmt.std_formatter
39543965
"Undo triggered by goal resumption\n%!";
39553966
[%tcall next_alt alts]
39563967
| Some ({ depth; program; goal; gid = gid [@trace] } :: gs) ->
3957-
run depth program goal (gid[@trace]) gs FNil alts cutto_alts
3968+
run depth program goal (gid[@trace]) gs Done alts cutto_alts
39583969
| Some [] -> alts)
3959-
| FCons (_,[],_) -> anomaly "empty stack frame"
3960-
| FCons(cutto_alts, { depth; program; goal; gid = gid [@trace] } :: gs, next) ->
3970+
| SolveGoals { brothers = []; _ } -> anomaly "empty continuation"
3971+
| SolveGoals { cutto_alts; brothers = { depth; program; goal; gid = gid [@trace] } :: gs; next } ->
39613972
run depth program goal (gid[@trace]) gs next alts cutto_alts
3973+
| ExitSLGRoot _ -> assert false
3974+
| TableSolution _ -> assert false
39623975

39633976
and resume_all () : goal list option =
39643977
(* if fm then Some [] else *)
@@ -4028,20 +4041,20 @@ end;*)
40284041
end
40294042

40304043
and next_alt alts =
4031-
if alts == noalts then raise No_clause
4032-
else
4033-
let { program = p; clauses; agoal_hd = k; ogoal_arg = arg; ogoal_args = args; agid = gid [@trace]; goals = gs; stack = next;
4034-
trail = old_trail; state = old_state;
4035-
adepth = depth; cutto_alts = cutto_alts; next = alts} = alts in
4036-
T.undo ~old_trail ~old_state ();
4037-
4038-
[%trace "run" ~rid begin
4039-
[%cur_pred (Some (C.show k))];
4040-
[%spyl "user:curgoal" ~rid ~gid (uppterm depth [] ~argsdepth:0 empty_env) [Const k;App(k,arg,args)]];
4041-
[%spy "user:rule" ~rid ~gid pp_string "backchain"];
4042-
[%spyl "user:rule:backchain:candidates" ~rid ~gid (pp_candidate ~depth ~k) clauses];
4043-
[%tcall backchain depth p (k, arg, args, gs) (gid[@trace]) next alts cutto_alts clauses]
4044-
end]
4044+
match alts with
4045+
| ExploreAnotherSLDPath { program = p; clauses; path; agid = gid [@trace]; stack = next;
4046+
trail = old_trail; state = old_state;
4047+
adepth = depth; cutto_alts = cutto_alts; alts} ->
4048+
T.undo ~old_trail ~old_state ();
4049+
[%trace "run" ~rid begin
4050+
[%cur_pred (Some (C.show path.predicate))];
4051+
[%spyl "user:curgoal" ~rid ~gid (uppterm depth [] ~argsdepth:0 empty_env) [Const path.predicate;App(path.predicate,path.fst_arg,path.other_args)]];
4052+
[%spy "user:rule" ~rid ~gid pp_string "backchain"];
4053+
[%spyl "user:rule:backchain:candidates" ~rid ~gid (pp_candidate ~depth ~k:(path.predicate)) clauses];
4054+
[%tcall backchain depth p path (gid[@trace]) next alts cutto_alts clauses]
4055+
end]
4056+
| UnblockSLGGenerator _ -> assert false
4057+
| Noalts -> raise No_clause
40454058
in
40464059

40474060
(* Finally the runtime *)
@@ -4077,7 +4090,7 @@ end;*)
40774090
let gid[@trace] = UUID.make () in
40784091
[%spy "user:newgoal" ~rid ~gid (uppterm initial_depth [] ~argsdepth:0 empty_env) initial_goal];
40794092
set T.trail (T.empty ());
4080-
run initial_depth !orig_prolog_program initial_goal (gid[@trace]) [] FNil noalts noalts) in
4093+
run initial_depth !orig_prolog_program initial_goal (gid[@trace]) [] Done Noalts Noalts) in
40814094
let destroy () = () in
40824095
let next_solution = exec next_alt in
40834096
incr max_runtime_id;
@@ -4107,8 +4120,8 @@ let mk_outcome search get_cs assignments depth =
41074120
} in
41084121
Success solution, alts
41094122
with
4110-
| No_clause (*| Non_linear*) -> Failure, noalts
4111-
| No_more_steps -> NoMoreSteps, noalts
4123+
| No_clause (*| Non_linear*) -> Failure, Noalts
4124+
| No_more_steps -> NoMoreSteps, Noalts
41124125

41134126
let execute_once ?max_steps ?delay_outside_fragment exec =
41144127
let { search; get } = make_runtime ?max_steps ?delay_outside_fragment exec in
@@ -4124,20 +4137,20 @@ let execute_once ?max_steps ?delay_outside_fragment exec =
41244137

41254138
let execute_loop ?delay_outside_fragment exec ~more ~pp =
41264139
let { search; next_solution; get; destroy } = make_runtime ?delay_outside_fragment exec in
4127-
let k = ref noalts in
4140+
let k = ref Noalts in
41284141
let do_with_infos f =
41294142
let time0 = Unix.gettimeofday() in
41304143
let o, alts = mk_outcome f (fun () -> get CS.Ugly.delayed, (exec.initial_depth,get CS.state), get CS.state |> State.end_execution, exec.query_arguments, { Data.uv_names = ref (get Pp.uv_names); table = get C.table }) exec.assignments exec.initial_depth in
41314144
let time1 = Unix.gettimeofday() in
41324145
k := alts;
41334146
pp (time1 -. time0) o in
41344147
do_with_infos search;
4135-
while !k != noalts do
4136-
if not(more()) then k := noalts else
4148+
while !k != Noalts do
4149+
if not(more()) then k := Noalts else
41374150
try do_with_infos (fun () -> next_solution !k)
41384151
with
4139-
| No_clause -> pp 0.0 Failure; k := noalts; [%end_trace "execute_loop" ~rid]
4140-
| e -> pp 0.0 Failure; k := noalts; [%end_trace "execute_loop" ~rid]; raise e
4152+
| No_clause -> pp 0.0 Failure; k := Noalts; [%end_trace "execute_loop" ~rid]
4153+
| e -> pp 0.0 Failure; k := Noalts; [%end_trace "execute_loop" ~rid]; raise e
41414154
done
41424155
;;
41434156

trace/ppx/trace_ppx.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@ let map_trace = object(self)
156156
let lbls = lbls |> List.filter (fun { pld_attributes = l; _ } ->
157157
not (has_iftrace_attribute l)) in
158158
{ tyd with ptype_kind = Ptype_record lbls }
159+
| Ptype_variant l ->
160+
let aux ({ pcd_args; _ } as pcd) =
161+
match pcd_args with
162+
| Pcstr_record lbls when not !enabled ->
163+
let lbls = lbls |> List.filter (fun { pld_attributes = l; _ } ->
164+
not (has_iftrace_attribute l)) in
165+
{pcd with pcd_args = Pcstr_record lbls }
166+
| _ -> pcd in
167+
let l = List.map aux l in
168+
{ tyd with ptype_kind = Ptype_variant l }
159169
| _ -> tyd
160170

161171
method! expression e =

0 commit comments

Comments
 (0)