@@ -186,22 +186,6 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
186
186
-- ``Has_Orphan`` is set to whether at least one atom is an "orphan", that
187
187
-- is to say it is not part of the resulting sorted collection.
188
188
189
- function Evaluate_Atoms
190
- (Sorted_Atoms : Atomic_Relation_Vectors.Elements_Array) return Boolean;
191
- -- Evaluate the given sequence of sorted atoms (see ``Topo_Sort``) and
192
- -- return whether they are all satisfied: if they are, the logic variables
193
- -- are assigned values, so it is possible to invoke the user callback for
194
- -- solutions.
195
-
196
- function Has_Contradiction
197
- (Atoms, Unifies : Atomic_Relation_Vector;
198
- Vars : Logic_Var_Array;
199
- Sort_Ctx : in out Sort_Context) return Boolean;
200
- -- Return whether the given sequence of atoms contains a contradiction,
201
- -- i.e. if two or more of its atoms make each other unsatisfied. This
202
- -- function works even for incomplete sequences, for instance when one atom
203
- -- uses a variable that no atom defines.
204
-
205
189
type Solving_Context is record
206
190
Cb : Callback_Type;
207
191
-- User callback, to be called when a solution is found. Returns whether
@@ -232,6 +216,10 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
232
216
Anys : Any_Relation_Vector;
233
217
-- Remaining list of ``Any`` relations to traverse
234
218
219
+ Timeout : Natural;
220
+ -- Number of times left we allow ourselves to evaluate an atom before
221
+ -- aborting the solver. If 0, no timeout applies.
222
+
235
223
Cut_Dead_Branches : Boolean := False;
236
224
-- Optimization that will cut branches that necessarily contain falsy
237
225
-- solutions.
@@ -263,6 +251,23 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
263
251
procedure Destroy (Ctx : in out Solving_Context);
264
252
-- Destroy a solving context, and associated data
265
253
254
+ function Evaluate_Atoms
255
+ (Ctx : in out Solving_Context;
256
+ Sorted_Atoms : Atomic_Relation_Vectors.Elements_Array) return Boolean;
257
+ -- Evaluate the given sequence of sorted atoms (see ``Topo_Sort``) and
258
+ -- return whether they are all satisfied: if they are, the logic variables
259
+ -- are assigned values, so it is possible to invoke the user callback for
260
+ -- solutions.
261
+
262
+ function Has_Contradiction
263
+ (Atoms, Unifies : Atomic_Relation_Vector;
264
+ Vars : Logic_Var_Array;
265
+ Ctx : in out Solving_Context) return Boolean;
266
+ -- Return whether the given sequence of atoms contains a contradiction,
267
+ -- i.e. if two or more of its atoms make each other unsatisfied. This
268
+ -- function works even for incomplete sequences, for instance when one atom
269
+ -- uses a variable that no atom defines.
270
+
266
271
function Solve_Compound
267
272
(Self : Compound_Relation; Ctx : in out Solving_Context) return Boolean;
268
273
-- Look for valid solutions in ``Self`` & ``Ctx``. Return whether to
@@ -829,13 +834,60 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
829
834
return Sorted_Atoms (1 .. Last_Atom_Index);
830
835
end Topo_Sort ;
831
836
837
+ -- -----------
838
+ -- Destroy --
839
+ -- -----------
840
+
841
+ procedure Destroy (Sort_Ctx : in out Sort_Context) is
842
+ begin
843
+ Sort_Ctx.N_Preds.Destroy;
844
+ Sort_Ctx.Working_Set.Destroy;
845
+ for Atoms of Sort_Ctx.Using_Atoms.all loop
846
+ Atoms.Destroy;
847
+ end loop ;
848
+ Free (Sort_Ctx.Using_Atoms);
849
+ end Destroy ;
850
+
851
+ -- -----------
852
+ -- Destroy --
853
+ -- -----------
854
+
855
+ procedure Destroy (Ctx : in out Solving_Context) is
856
+ begin
857
+ Ctx.Unifies.Destroy;
858
+ Ctx.Atoms.Destroy;
859
+ Ctx.Anys.Destroy;
860
+ Destroy (Ctx.Sort_Ctx);
861
+
862
+ -- Cleanup logic vars for future solver runs using them. Note that no
863
+ -- aliasing information is supposed to be left at this stage.
864
+
865
+ for V of Ctx.Vars.all loop
866
+ Reset (V);
867
+ Set_Id (V, 0 );
868
+ end loop ;
869
+ Free (Ctx.Vars);
870
+ end Destroy ;
871
+
832
872
-- ------------------
833
873
-- Evaluate_Atoms --
834
874
-- ------------------
835
875
836
876
function Evaluate_Atoms
837
- (Sorted_Atoms : Atomic_Relation_Vectors.Elements_Array) return Boolean is
877
+ (Ctx : in out Solving_Context;
878
+ Sorted_Atoms : Atomic_Relation_Vectors.Elements_Array) return Boolean is
838
879
begin
880
+ -- If we have a timeout, apply it
881
+
882
+ if Ctx.Timeout > 0 then
883
+ if Sorted_Atoms'Length > Ctx.Timeout then
884
+ raise Timeout_Error;
885
+ end if ;
886
+ Ctx.Timeout := Ctx.Timeout - Sorted_Atoms'Length;
887
+ end if ;
888
+
889
+ -- Evaluate each individual atom
890
+
839
891
for Atom of Sorted_Atoms loop
840
892
if not Solve_Atomic (Atom) then
841
893
if Solv_Trace.Is_Active then
@@ -856,28 +908,28 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
856
908
function Has_Contradiction
857
909
(Atoms, Unifies : Atomic_Relation_Vector;
858
910
Vars : Logic_Var_Array;
859
- Sort_Ctx : in out Sort_Context ) return Boolean
911
+ Ctx : in out Solving_Context ) return Boolean
860
912
is
861
913
Had_Exception : Boolean := False;
862
914
Exc : Exception_Occurrence;
863
915
864
916
Result : Boolean;
865
917
begin
866
- Sort_Ctx.Has_Contradiction_Counter :=
867
- Sort_Ctx.Has_Contradiction_Counter + 1 ;
918
+ Ctx. Sort_Ctx.Has_Contradiction_Counter :=
919
+ Ctx. Sort_Ctx.Has_Contradiction_Counter + 1 ;
868
920
869
921
if Solv_Trace.Is_Active then
870
922
Solv_Trace.Increase_Indent
871
923
(" Looking for a contradiction (number"
872
- & Sort_Ctx.Has_Contradiction_Counter'Image & " )" );
924
+ & Ctx. Sort_Ctx.Has_Contradiction_Counter'Image & " )" );
873
925
Solv_Trace.Trace (Image (Atoms));
874
926
end if ;
875
927
876
928
declare
877
929
use Atomic_Relation_Vectors;
878
930
Dummy : Boolean;
879
931
Sorted_Atoms : constant Elements_Array :=
880
- Topo_Sort (Atoms, Unifies, Vars, Sort_Ctx, Dummy);
932
+ Topo_Sort (Atoms, Unifies, Vars, Ctx. Sort_Ctx, Dummy);
881
933
begin
882
934
if Solv_Trace.Is_Active then
883
935
Solv_Trace.Trace (" After partial topo sort" );
@@ -897,7 +949,7 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
897
949
-- the order in which the solver finds solutions.
898
950
899
951
begin
900
- Result := not Evaluate_Atoms (Sorted_Atoms);
952
+ Result := not Evaluate_Atoms (Ctx, Sorted_Atoms);
901
953
exception
902
954
when E : others =>
903
955
Save_Occurrence (Exc, E);
@@ -927,41 +979,6 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
927
979
end ;
928
980
end Has_Contradiction ;
929
981
930
- -- -----------
931
- -- Destroy --
932
- -- -----------
933
-
934
- procedure Destroy (Sort_Ctx : in out Sort_Context) is
935
- begin
936
- Sort_Ctx.N_Preds.Destroy;
937
- Sort_Ctx.Working_Set.Destroy;
938
- for Atoms of Sort_Ctx.Using_Atoms.all loop
939
- Atoms.Destroy;
940
- end loop ;
941
- Free (Sort_Ctx.Using_Atoms);
942
- end Destroy ;
943
-
944
- -- -----------
945
- -- Destroy --
946
- -- -----------
947
-
948
- procedure Destroy (Ctx : in out Solving_Context) is
949
- begin
950
- Ctx.Unifies.Destroy;
951
- Ctx.Atoms.Destroy;
952
- Ctx.Anys.Destroy;
953
- Destroy (Ctx.Sort_Ctx);
954
-
955
- -- Cleanup logic vars for future solver runs using them. Note that no
956
- -- aliasing information is supposed to be left at this stage.
957
-
958
- for V of Ctx.Vars.all loop
959
- Reset (V);
960
- Set_Id (V, 0 );
961
- end loop ;
962
- Free (Ctx.Vars);
963
- end Destroy ;
964
-
965
982
-- ------------
966
983
-- Used_Var --
967
984
-- ------------
@@ -1140,7 +1157,7 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1140
1157
1141
1158
-- Once the topological sort has been done, we just have to solve
1142
1159
-- every relation in order. Abort if one doesn't solve.
1143
- if not Evaluate_Atoms (Sorted_Atoms) then
1160
+ if not Evaluate_Atoms (Ctx, Sorted_Atoms) then
1144
1161
return Cleanup (True);
1145
1162
end if ;
1146
1163
@@ -1351,7 +1368,7 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1351
1368
1352
1369
Create_Aliases;
1353
1370
if Has_Contradiction
1354
- (Ctx.Atoms, Ctx.Unifies, Ctx.Vars.all , Ctx.Sort_Ctx )
1371
+ (Ctx.Atoms, Ctx.Unifies, Ctx.Vars.all , Ctx)
1355
1372
then
1356
1373
if Solv_Trace.Active then
1357
1374
Solv_Trace.Trace (" Aborting due to exp res optim" );
@@ -1426,7 +1443,8 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1426
1443
(Self : Relation;
1427
1444
Solution_Callback : access function
1428
1445
(Vars : Logic_Var_Array) return Boolean;
1429
- Solve_Options : Solve_Options_Type := Default_Options)
1446
+ Solve_Options : Solve_Options_Type := Default_Options;
1447
+ Timeout : Natural)
1430
1448
is
1431
1449
PRel : Prepared_Relation;
1432
1450
Rel : Relation renames PRel.Rel;
@@ -1454,6 +1472,7 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1454
1472
1455
1473
PRel := Prepare_Relation (Self);
1456
1474
Ctx := Create (Solution_Callback'Unrestricted_Access.all , PRel.Vars);
1475
+ Ctx.Timeout := Timeout;
1457
1476
Ctx.Cut_Dead_Branches := Solve_Options.Cut_Dead_Branches;
1458
1477
1459
1478
declare
@@ -1506,7 +1525,8 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1506
1525
1507
1526
function Solve_First
1508
1527
(Self : Relation;
1509
- Solve_Options : Solve_Options_Type := Default_Options) return Boolean
1528
+ Solve_Options : Solve_Options_Type := Default_Options;
1529
+ Timeout : Natural) return Boolean
1510
1530
is
1511
1531
Ret : Boolean := False;
1512
1532
@@ -1550,7 +1570,7 @@ package body Langkit_Support.Adalog.Symbolic_Solver is
1550
1570
end Callback ;
1551
1571
1552
1572
begin
1553
- Solve (Self, Callback'Access , Solve_Options);
1573
+ Solve (Self, Callback'Access , Solve_Options, Timeout );
1554
1574
if Tracked_Vars /= null then
1555
1575
for TV of Tracked_Vars.all loop
1556
1576
if TV.Defined then
0 commit comments