Skip to content

Commit 20473b1

Browse files
pmderodatraph-amiard
authored andcommitted
Adalog: add a N_Predicate atomc relation kind
TN: SB20-024 For libadalang/langkit#618
1 parent 25b0ce4 commit 20473b1

8 files changed

+271
-27
lines changed

support/langkit_support-adalog-generic_main_support.ads

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ package Langkit_Support.Adalog.Generic_Main_Support is
8282
is
8383
(+Create_Propagate (L, R, Conv, -Dbg_String));
8484

85+
function N_Propagate
86+
(To : Refs.Logic_Var;
87+
Comb : Combiner_Type'Class;
88+
Vars : Logic_Var_Array;
89+
Dbg_String : String := "") return Relation
90+
is (+Create_N_Propagate (To, Comb, Vars, -Dbg_String));
91+
8592
function Unify
8693
(L, R : Refs.Logic_Var; Dbg_String : String := "") return Relation
8794
is (+Create_Unify (L, R, -Dbg_String));

support/langkit_support-adalog-solver.adb

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ package body Langkit_Support.Adalog.Solver is
753753
when Assign | True | False => True,
754754

755755
when Propagate => Append_Definition (Atom.From),
756+
when N_Propagate => Append_Definitions (Atom.Comb_Vars),
756757
when Predicate => Append_Definition (Atom.Target),
757758
when N_Predicate => Append_Definitions (Atom.Vars),
758759

@@ -972,10 +973,15 @@ package body Langkit_Support.Adalog.Solver is
972973
is
973974
-- We handle Unify here, even though it is not strictly treated in the
974975
-- dependency graph, so that the Unify_From variable is registered in
975-
-- the list of variables of the equation. TODO??? Might be cleaner to
976-
-- have a separate function to return all variables a relation uses?
976+
-- the list of variables of the equation.
977+
--
978+
-- We also pretend that N_Propagate has no dependency here because it
979+
-- depends on multiple variables. Callers should handle it separately.
980+
--
981+
-- TODO??? Might be cleaner to have a separate function to return all
982+
-- variables a relation uses?
977983
(case Self.Kind is
978-
when Assign | True | False | N_Predicate => null,
984+
when Assign | N_Propagate | True | False | N_Predicate => null,
979985
when Propagate => Self.From,
980986
when Predicate => Self.Target,
981987
when Unify => Self.Unify_From);
@@ -991,8 +997,8 @@ package body Langkit_Support.Adalog.Solver is
991997
-- the list of variables of the equation. TODO??? Might be cleaner to
992998
-- have a separate function to return all variables a relation defines?
993999
(case Self.Kind is
994-
when Assign | Propagate | Unify => Self.Target,
995-
when Predicate | True | False | N_Predicate => null);
1000+
when Assign | Propagate | N_Propagate | Unify => Self.Target,
1001+
when Predicate | True | False | N_Predicate => null);
9961002

9971003
-----------------
9981004
-- To_Relation --
@@ -1683,6 +1689,27 @@ package body Langkit_Support.Adalog.Solver is
16831689
Debug_String => Debug_String);
16841690
end Create_Propagate;
16851691

1692+
------------------------
1693+
-- Create_N_Propagate --
1694+
------------------------
1695+
1696+
function Create_N_Propagate
1697+
(To : Logic_Var;
1698+
Comb : Combiner_Type'Class;
1699+
Logic_Vars : Logic_Var_Array;
1700+
Debug_String : String_Access := null) return Relation
1701+
is
1702+
Vars_Vec : Logic_Var_Vector := Logic_Var_Vectors.Empty_Vector;
1703+
begin
1704+
Vars_Vec.Concat (Logic_Var_Vectors.Elements_Array (Logic_Vars));
1705+
return To_Relation
1706+
(Atomic_Relation_Type'(Kind => N_Propagate,
1707+
Comb_Vars => Vars_Vec,
1708+
Comb => new Combiner_Type'Class'(Comb),
1709+
Target => To),
1710+
Debug_String => Debug_String);
1711+
end Create_N_Propagate;
1712+
16861713
----------------------
16871714
-- Create_Propagate --
16881715
----------------------
@@ -1803,6 +1830,10 @@ package body Langkit_Support.Adalog.Solver is
18031830
end if;
18041831
Free (Self.Conv);
18051832

1833+
when N_Propagate =>
1834+
Destroy (Self.Comb.all);
1835+
Free (Self.Comb);
1836+
18061837
when Predicate =>
18071838
Destroy (Self.Pred.all);
18081839
Free (Self.Pred);
@@ -1852,6 +1883,14 @@ package body Langkit_Support.Adalog.Solver is
18521883
function Solve_Atomic (Self : Atomic_Relation) return Boolean is
18531884
Atom : Atomic_Relation_Type renames Self.Atomic_Rel;
18541885

1886+
function Converted_Val (Val : Value_Type) return Value_Type
1887+
is
1888+
(if Atom.Conv /= null
1889+
then Atom.Conv.Convert_Wrapper (Val)
1890+
else Val);
1891+
-- Assuming ``Atom`` is an Assign or Propagate atom, return ``Val``
1892+
-- transformed by its converter.
1893+
18551894
function Assign_Val (Val : Value_Type) return Boolean;
18561895
-- Tries to assign ``Val`` to ``Atom.Target`` and return True either if
18571896
-- ``Atom.Target`` already has a value compatible with ``Val``, or if
@@ -1860,33 +1899,56 @@ package body Langkit_Support.Adalog.Solver is
18601899
-- This assumes that ``Self`` is either an ``Assign`` or a `Propagate``
18611900
-- relation.
18621901

1902+
procedure Get_Values (Vars : Logic_Var_Vector; Vals : out Value_Array);
1903+
-- Assign to ``Vals`` the value of the variables in ``Vars``.
1904+
--
1905+
-- This assumes that ``Vars`` and ``Vals`` have the same bounds. Note
1906+
-- that we could turn this into a function that returns the array, but
1907+
-- this would require secondary stack support and its overhead, whereas
1908+
-- this is performance critical code.
1909+
18631910
----------------
18641911
-- Assign_Val --
18651912
----------------
18661913

18671914
function Assign_Val (Val : Value_Type) return Boolean is
1868-
Conv_Val : constant Value_Type :=
1869-
(if Atom.Conv /= null
1870-
then Atom.Conv.Convert_Wrapper (Val)
1871-
else Val);
18721915
begin
18731916
if Is_Defined (Atom.Target) then
1874-
return Conv_Val = Get_Value (Atom.Target);
1917+
return Val = Get_Value (Atom.Target);
18751918
else
1876-
Set_Value (Atom.Target, Conv_Val);
1919+
Set_Value (Atom.Target, Val);
18771920
return True;
18781921
end if;
18791922
end Assign_Val;
18801923

1924+
----------------
1925+
-- Get_Values --
1926+
----------------
1927+
1928+
procedure Get_Values (Vars : Logic_Var_Vector; Vals : out Value_Array) is
1929+
begin
1930+
for I in Vals'Range loop
1931+
Vals (I) := Get_Value (Vars.Get (I));
1932+
end loop;
1933+
end Get_Values;
1934+
18811935
Ret : Boolean;
18821936
begin
18831937
case Atom.Kind is
18841938
when Assign =>
1885-
Ret := Assign_Val (Atom.Val);
1939+
Ret := Assign_Val (Converted_Val (Atom.Val));
18861940

18871941
when Propagate =>
18881942
pragma Assert (Is_Defined (Atom.From));
1889-
Ret := Assign_Val (Get_Value (Atom.From));
1943+
Ret := Assign_Val (Converted_Val (Get_Value (Atom.From)));
1944+
1945+
when N_Propagate =>
1946+
declare
1947+
Vals : Value_Array (1 .. Atom.Comb_Vars.Length);
1948+
begin
1949+
Get_Values (Atom.Comb_Vars, Vals);
1950+
Ret := Assign_Val (Atom.Comb.Combine_Wrapper (Vals));
1951+
end;
18901952

18911953
when Predicate =>
18921954
pragma Assert (Is_Defined (Atom.Target));
@@ -1896,10 +1958,7 @@ package body Langkit_Support.Adalog.Solver is
18961958
declare
18971959
Vals : Value_Array (1 .. Atom.Vars.Length);
18981960
begin
1899-
for I in Atom.Vars.First_Index .. Atom.Vars.Last_Index loop
1900-
Vals (I) := Get_Value (Atom.Vars.Get (I));
1901-
end loop;
1902-
1961+
Get_Values (Atom.Vars, Vals);
19031962
Ret := Atom.N_Pred.Call_Wrapper (Vals);
19041963
end;
19051964

@@ -1931,6 +1990,22 @@ package body Langkit_Support.Adalog.Solver is
19311990
function Prop_Image (Left, Right : String) return String
19321991
is
19331992
(Left & " <- " & Right_Image (Right));
1993+
1994+
function Var_Args_Image (Vars : Logic_Var_Vector) return String;
1995+
1996+
--------------------
1997+
-- Var_Args_Image --
1998+
--------------------
1999+
2000+
function Var_Args_Image (Vars : Logic_Var_Vector) return String is
2001+
Vars_Image : XString_Array (1 .. Vars.Length);
2002+
begin
2003+
for I in Vars_Image'Range loop
2004+
Vars_Image (I) := To_XString (Image (Vars.Get (I)));
2005+
end loop;
2006+
return "(" & To_XString (", ").Join (Vars_Image).To_String & ")";
2007+
end Var_Args_Image;
2008+
19342009
begin
19352010
case Self.Kind is
19362011
when Propagate =>
@@ -1940,6 +2015,10 @@ package body Langkit_Support.Adalog.Solver is
19402015
return Prop_Image
19412016
(Image (Self.Target), Logic_Vars.Value_Image (Self.Val));
19422017

2018+
when N_Propagate =>
2019+
return Image (Self.Target) & " <- " & Self.Comb.Image
2020+
& Var_Args_Image (Self.Comb_Vars);
2021+
19432022
when Predicate =>
19442023
declare
19452024
Full_Img : constant String :=
@@ -1954,16 +2033,11 @@ package body Langkit_Support.Adalog.Solver is
19542033
declare
19552034
Full_Img : constant String :=
19562035
Self.N_Pred.Full_Image (Logic_Var_Array (Self.Vars.To_Array));
1957-
Vars_Image : XString_Array (1 .. Self.Vars.Length);
19582036
begin
1959-
if Full_Img /= "" then
1960-
return Full_Img;
1961-
end if;
1962-
for I in Vars_Image'Range loop
1963-
Vars_Image (I) := To_XString (Image (Self.Vars.Get (I)));
1964-
end loop;
1965-
return Self.N_Pred.Image
1966-
& "?(" & To_XString (", ").Join (Vars_Image).To_String & ")";
2037+
return
2038+
(if Full_Img /= ""
2039+
then Full_Img
2040+
else Self.N_Pred.Image & "?" & Var_Args_Image (Self.Vars));
19672041
end;
19682042

19692043
when True =>

support/langkit_support-adalog-solver.ads

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ package Langkit_Support.Adalog.Solver is
140140
-- If ``Conv`` is provided, the actually assigned value is the result of
141141
-- ``Conv`` when called on ``From``'s value.
142142

143+
function Create_N_Propagate
144+
(To : Logic_Var;
145+
Comb : Combiner_Type'Class;
146+
Logic_Vars : Logic_Var_Array;
147+
Debug_String : String_Access := null) return Relation;
148+
-- Create a relation that will solve successfully if it is possible to
149+
-- assign to ``To`` the value computed by calling ``Comb`` on the given
150+
-- ``Logic_Vars``.
151+
143152
function Create_Domain
144153
(Logic_Var : Logic_Vars.Logic_Var;
145154
Domain : Value_Array;
@@ -182,11 +191,14 @@ package Langkit_Support.Adalog.Solver is
182191
private
183192

184193
type Converter_Access is access all Converter_Type'Class;
194+
type Combiner_Access is access all Combiner_Type'Class;
185195
type Predicate_Access is access all Predicate_Type'Class;
186196
type N_Predicate_Access is access all N_Predicate_Type'Class;
187197

188198
procedure Free is new Ada.Unchecked_Deallocation
189199
(Converter_Type'Class, Converter_Access);
200+
procedure Free is new Ada.Unchecked_Deallocation
201+
(Combiner_Type'Class, Combiner_Access);
190202
procedure Free is new Ada.Unchecked_Deallocation
191203
(Predicate_Type'Class, Predicate_Access);
192204
procedure Free is new Ada.Unchecked_Deallocation
@@ -200,7 +212,7 @@ private
200212
-- Atomic_Relation --
201213
---------------------
202214

203-
type Atomic_Kind is (Propagate, Unify, Assign, Predicate,
215+
type Atomic_Kind is (Propagate, N_Propagate, Unify, Assign, Predicate,
204216
N_Predicate, True, False);
205217

206218
type Atomic_Relation_Type (Kind : Atomic_Kind := Propagate) is record
@@ -228,6 +240,14 @@ private
228240
when others => null;
229241
end case;
230242

243+
when N_Propagate =>
244+
Comb_Vars : Logic_Var_Vector;
245+
-- List of logic variables used by the converter
246+
247+
Comb : Combiner_Access;
248+
-- Combiner function to assign a value to Target that is computed
249+
-- from the value of N_Propagate_Vars.
250+
231251
when Predicate =>
232252
Pred : Predicate_Access;
233253
-- The predicate that will be applied as part of this relation

support/langkit_support-adalog-solver_interface.adb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ package body Langkit_Support.Adalog.Solver_Interface is
3636
type Predicate_Fn is access function (V : Value_Type) return Boolean;
3737
type Converter_Fn is access function (V : Value_Type) return Value_Type;
3838
type N_Predicate_Fn is access function (Vs : Value_Array) return Boolean;
39+
type Combiner_Fn is access function (Vs : Value_Array) return Value_Type;
3940

4041
type Predicate_Fn_Wrapper is new Predicate_Type with record
4142
Callback : Predicate_Fn;
@@ -73,6 +74,18 @@ package body Langkit_Support.Adalog.Solver_Interface is
7374
overriding function Image (Self : Converter_Wrapper) return String
7475
is (Self.Name.To_String);
7576

77+
type Combiner_Wrapper is new Combiner_Type with record
78+
Callback : Combiner_Fn;
79+
Name : XString;
80+
end record;
81+
82+
overriding function Combine
83+
(Self : Combiner_Wrapper; Vs : Value_Array) return Value_Type
84+
is (Self.Callback (Vs));
85+
86+
overriding function Image (Self : Combiner_Wrapper) return String
87+
is (Self.Name.To_String);
88+
7689
------------------
7790
-- Call_Wrapper --
7891
------------------
@@ -120,6 +133,23 @@ package body Langkit_Support.Adalog.Solver_Interface is
120133
return Self.Cache_Value;
121134
end Convert_Wrapper;
122135

136+
---------------------
137+
-- Combine_Wrapper --
138+
---------------------
139+
140+
function Combine_Wrapper
141+
(Self : in out Combiner_Type'Class;
142+
Vals : Logic_Vars.Value_Array) return Value_Type
143+
is
144+
begin
145+
if not Self.Cache_Set or else Self.Cache_Key /= Vals then
146+
Self.Cache_Value := Self.Combine (Vals);
147+
Self.Cache_Set := True;
148+
Self.Cache_Key := Vals;
149+
end if;
150+
return Self.Cache_Value;
151+
end Combine_Wrapper;
152+
123153
---------------
124154
-- Converter --
125155
---------------
@@ -194,4 +224,24 @@ package body Langkit_Support.Adalog.Solver_Interface is
194224
Name => To_XString (Pred_Name));
195225
end N_Predicate;
196226

227+
--------------
228+
-- Combiner --
229+
--------------
230+
231+
function Combiner
232+
(Comb : access function (V : Value_Array) return Value_Type;
233+
Arity : Positive;
234+
Comb_Name : String := "Combiner") return Combiner_Type'Class
235+
is
236+
begin
237+
return Combiner_Wrapper'
238+
(N => Arity,
239+
Cache_Set => False,
240+
Cache_Key => <>,
241+
Cache_Value => <>,
242+
Ref_Count => 1,
243+
Callback => Comb'Unrestricted_Access.all,
244+
Name => To_XString (Comb_Name));
245+
end Combiner;
246+
197247
end Langkit_Support.Adalog.Solver_Interface;

0 commit comments

Comments
 (0)