1 |
On pon, 2017-06-05 at 09:55 +0200, Alexis Ballier wrote: |
2 |
> On Sun, 4 Jun 2017 10:59:38 +0200 |
3 |
> Alexis Ballier <aballier@g.o> wrote: |
4 |
> |
5 |
> > Here's a quick n dirty code to play with, based on yours: |
6 |
> > https://github.com/aballier/required-use |
7 |
> |
8 |
> I've run that on the whole tree (considering all ebuilds with non |
9 |
> empty REQUIRED_USE), some stats: |
10 |
> |
11 |
> $ time python3 classify.py requsel |
12 |
> Stats: |
13 |
> Parse error: 16 |
14 |
|
15 |
Hmm, how did you get those numbers? I just tested parsing and found only |
16 |
7 unique REQUIRED_USE entries that fail. However, my sample file is |
17 |
only around 1000 entries long, so either I failed to get all of them, or |
18 |
you didn't deduplicate your list ;-). More on it below. |
19 |
|
20 |
> Good: 8316 |
21 |
> Need topo sort: 140 |
22 |
> Cyclic: 57 |
23 |
> |
24 |
> real 0m2.996s |
25 |
> user 0m2.950s |
26 |
> sys 0m0.004s |
27 |
> |
28 |
> |
29 |
> Running time is good I think. |
30 |
> Parse error is some nested construct not supported by your parser that |
31 |
> I have not fixed either. |
32 |
|
33 |
Yes, the time is great. It means we can actually think about integrating |
34 |
it with repoman/pkgcheck. |
35 |
|
36 |
> The cycle is mostly due to: |
37 |
> $ python3 nsolve.py 'llvm? ( gallium ) gallium? ( llvm )' |
38 |
> [...] |
39 |
> toposort.CircularDependencyError: Circular dependencies exist among |
40 |
> these items: {[gallium]? => [llvm]:{[llvm]? => [gallium]}, [llvm]? => |
41 |
> [gallium]:{[gallium]? => [llvm]}} |
42 |
> |
43 |
> |
44 |
> This is something I had overseen when replacing 'a q'_j is some p_i and |
45 |
> one of q_1 ... q_m might be false' by only 'a q'_j is some p_i'; it can |
46 |
> be replaced without changing anything in the way PM would solve it by |
47 |
> "a q'_j is some p_i and the set of {q_j} is not a subset of q' union |
48 |
> p'" (that is, {q_i} is not trivially true if the 2nd clause is |
49 |
> applied). Extending that, we get those stats: |
50 |
|
51 |
I'm not even trying to understand the things you say with indexes but I |
52 |
trust you know what you're doing. For completeness, we need to consider |
53 |
three cross-dependent states: |
54 |
|
55 |
a. a? ( b ) b? ( a ) |
56 |
|
57 |
i.e.: |
58 |
|
59 |
y_1 = y_2 = x_1 v x_2 |
60 |
|
61 |
iow, enabling either of the flags causes both of them being enabled. I'm |
62 |
not sure if we have a valid use case to keep such flags long-term but |
63 |
short-term they could be useful to handle transition periods when |
64 |
upstream merges two features (or makes them cross-dependent) and we want |
65 |
to preserve compatibility with split flags. |
66 |
|
67 |
b. !a? ( !b ) !b? ( !a ) |
68 |
|
69 |
i.e.: |
70 |
|
71 |
y_1 = y_2 = x_1 ^ x_2 |
72 |
|
73 |
iow, you have to enable both flags to keep them enabled. Not sure if we |
74 |
have any valid use case for this. |
75 |
|
76 |
c. a? ( b ) !a? ( !b ) |
77 |
|
78 |
i.e. |
79 |
|
80 |
y_1 = y_2 = x_1 |
81 |
|
82 |
This mostly a reduced result of: |
83 |
|
84 |
a? ( || ( b c d ... ) ) !a? ( !b !c !d ... ) |
85 |
|
86 |
[NB: it would be useful to have a short syntax for that] |
87 |
|
88 |
I suspect this will be commonly useful to express provider dependencies, |
89 |
i.e. enforcing a particular constraint for providers only when |
90 |
the feature flag is enabled, and disabling all provider flags when it is |
91 |
not. |
92 |
|
93 |
FWICS, my version solves all three cases correctly, and your does not |
94 |
explode on them. |
95 |
|
96 |
> I'll let you play with it, but for me it seems this would work quite |
97 |
> nicely. |
98 |
> |
99 |
|
100 |
Well, I guess it's time to hit the next level. For a start, we have to |
101 |
handle all-of groups, i.e.: |
102 |
|
103 |
( a b c ) |
104 |
|
105 |
Stand-alone makes little sense (and little trouble) but as you could |
106 |
have seen it's used nested in other thingies: |
107 |
|
108 |
1. || ( ( a b ) ( c d ) e ) |
109 |
|
110 |
2. ?? ( ( a b ) ( c d ) e ) |
111 |
|
112 |
3. ^^ ( ( a b ) ( c d ) e ) |
113 |
|
114 |
For verifying constraints, they are not bad. We just follow the generic |
115 |
rule that the branch evaluates to true if all subexpressions are true. |
116 |
|
117 |
For solving, it might be a little unclear on how to proceed with |
118 |
partially true branches but for the sake of simplicity I would just |
119 |
ignore them and behave as if they were false. That is, case (1) with |
120 |
USE='c' would result in 'a b' being enabled. |
121 |
|
122 |
The practical uses I've seen are: |
123 |
|
124 |
a. || ( deprecated ( gtk3 introspection ) ) |
125 |
|
126 |
I guess this one would be equivalent to: |
127 |
|
128 |
!gtk3? ( !introspection? ( deprecated ) ) |
129 |
|
130 |
b. ^^ ( ( !32bit 64bit ) ( 32bit !64bit ) ( 32bit 64bit ) ) |
131 |
|
132 |
This looks like a crazy way of saying: |
133 |
|
134 |
|| ( 32bit 64bit ) |
135 |
|
136 |
c. ^^ ( ( !ruby !s7 ) ( ruby !s7 ) ( !ruby s7 ) ) |
137 |
|
138 |
This looks like an insane version of: |
139 |
|
140 |
?? ( ruby s7 ) |
141 |
|
142 |
except that per my solver it just disables both when both are set ;-). |
143 |
|
144 |
Not sure if the extra complexity is worth for roughly one valid use |
145 |
case, and a lot of insanity. |
146 |
|
147 |
I've pushed a simple update to my parser to account for this. However, |
148 |
it doesn't support replace_nary atm, so it won't work for you. |
149 |
|
150 |
|
151 |
Of course past that there's a deeper insanity: all those constructs can |
152 |
be nested without limits. Verification is possible, solving maybe -- but |
153 |
I'm not sure if we even want to try to think what the correct solution |
154 |
would be. |
155 |
|
156 |
There's only one use of this: |
157 |
|
158 |
?? ( gl3plus ( || ( gles2 gles3 ) ) ) |
159 |
|
160 |
FWICS, it probably works like this; |
161 |
|
162 |
g g |
163 |
l l |
164 |
3 g g 3 g g |
165 |
p l l p l l |
166 |
l e e l e e |
167 |
u s s u s s |
168 |
s 2 3 | s 2 3 |
169 |
0 0 0 | 0 0 0 (==) |
170 |
0 0 1 | 0 0 1 (==) |
171 |
0 1 0 | 0 1 0 (==) |
172 |
0 1 1 | 0 1 1 (==) |
173 |
1 0 0 | 1 0 0 (==) |
174 |
1 0 1 | 1 0 1 [unsolvable due to loop] |
175 |
1 1 0 | 1 1 0 [unsolvable due to loop] |
176 |
1 1 1 | 1 1 1 [unsolvable due to loop] |
177 |
|
178 |
i.e. it would be equivalent to: |
179 |
|
180 |
gl3plus? ( !gles2 !gles3 ) |
181 |
|
182 |
unless the author meant something else and failed. |
183 |
|
184 |
The question is whether we want to: |
185 |
|
186 |
a. actually try to solve this nesting insanity, |
187 |
|
188 |
b. declare it unsupported and throw REQUIRED_USE mismatch on user, |
189 |
|
190 |
c. ban it altogether. |
191 |
|
192 |
-- |
193 |
Best regards, |
194 |
Michał Górny |