1 |
On Wed, 14 Jun 2017 00:13:42 +0200 |
2 |
Michał Górny <mgorny@g.o> wrote: |
3 |
|
4 |
> On wto, 2017-06-13 at 12:27 +0200, Alexis Ballier wrote: |
5 |
> > On Mon, 12 Jun 2017 21:17:16 +0200 |
6 |
> > Michał Górny <mgorny@g.o> wrote: |
7 |
> > |
8 |
> > > I've actually started typing the initial specification yesterday |
9 |
> > > [1]. As you can see, banning the extra constraints has made the |
10 |
> > > algorithms much simpler. In particular: |
11 |
> > > |
12 |
> > > 1. You do not have to define 'falsify' for anything other than |
13 |
> > > pure flags -- which makes it easy to inline it. |
14 |
> > > |
15 |
> > > 2. ||, ??, ^^ groups are only flat lists of flags -- which makes |
16 |
> > > reordering and processing them trivial. |
17 |
> > > |
18 |
> > > 3. The algorithm is recursive only on USE-conditional groups. This |
19 |
> > > makes it trivial to make it iterative. Optimizations become |
20 |
> > > trivially possible. |
21 |
> > |
22 |
> > |
23 |
> > While you're right in one sense, you're mixing two different things |
24 |
> > here. What you wrote *is* recursive. It does not recurse just |
25 |
> > because you're assuming a restricted syntax. You're only saving two |
26 |
> > things: you don't need to define how to enforce to false (that is 3 |
27 |
> > lines not 3 pages :=) ) and you're avoiding the nested use |
28 |
> > conditionals that are already ill defined per the current spec |
29 |
> > (foo? bar is equivalent to && ( foo bar ) when nested) which I |
30 |
> > believe is already another problem. |
31 |
> > |
32 |
> > Then, remember how I wanted to be much more drastic than you in the |
33 |
> > beginning by killing all ||,&&,^^ etc. and keep only use |
34 |
> > conditionals in REQUIRED_USE ? Well, that's where the complexity |
35 |
> > comes. The whole deal then is to define rewriting rules for the AST |
36 |
> > so that the algorithm you describe executes the exact same |
37 |
> > instructions but the new AST only has use conditionals. This is |
38 |
> > more like writing a compiler for the spec, so this does not belong |
39 |
> > to the spec and there is no issue here. |
40 |
> |
41 |
> I'm looking for a compromise here. Killing those groups completely is |
42 |
> going to make things harder for users. Keeping them with functionality |
43 |
> limited to what's used in ~99.9% ebuilds (based on your numbers) is |
44 |
> IMO a better choice. |
45 |
|
46 |
I already said I see the limited syntax as a good thing because it |
47 |
forces devs to write constraints that have a natural interpretation in |
48 |
how it is solved. However, you can't limit the syntax without a new |
49 |
EAPI, and more importantly, properly solving does not even require |
50 |
limiting the syntax. |
51 |
|
52 |
BTW, I don't know how you get that info from my data because I never |
53 |
voluntarily checked for a restricted syntax :) |
54 |
|
55 |
> > [BTW: checking the rewrite rules behave properly is what I meant by |
56 |
> > rebasing solve() on top of it and being happy with it] |
57 |
> |
58 |
> Could you reiterate the current solving rules (trueify/falsify)? Are |
59 |
> they equal to the ones you listed last, or does the current |
60 |
> implementation change anything? |
61 |
|
62 |
Let's recap a bit. nsolve() is poorly named and does not solve |
63 |
anything. It translates to implications and checks whether the |
64 |
implications solver will always provide a valid result in one pass. |
65 |
So, if you only care about solving rules, read your spec man. For the |
66 |
more general case it should behave like those trueify/falsify with |
67 |
the change that nested implications are interpreted as && (so no |
68 |
more !(a -> b) crap to worry about). |
69 |
|
70 |
If you take solve() as an implementation of your spec, you have: |
71 |
solve(x) <=> solve(to_impl.convert_to_implications(x)) when solve(x) |
72 |
is defined; with the added benefit that |
73 |
'solve(to_impl.convert_to_implications(x))' is defined and should |
74 |
provide proper results on the whole REQUIRED_USE syntax as currently |
75 |
defined (granted that nsolve(x) does not report anything wrong). |
76 |
|
77 |
> > > Nevertheless, feel free to play with the full implementation. If |
78 |
> > > you're interested, you can play with the complex cases more. In |
79 |
> > > particular, I'm wondering whether nsolve will actually consider |
80 |
> > > most of them solvable. |
81 |
> > > |
82 |
> > > As for the results, I think it is the point where we start |
83 |
> > > preparing pull requests with REQUIRED_USE changes to see whether |
84 |
> > > the developers agree with such changes. |
85 |
> > |
86 |
> > If by that you also include code cleanup and writing tests then |
87 |
> > yes :) |
88 |
> |
89 |
> I'm not sure if we're talking about the same thing. I'm talking about |
90 |
> filing pull requests against ebuilds whose REQUIRED_USE is rejected by |
91 |
> nsolve. I think it'd serve as a reasonable field test for whether |
92 |
> developers agree with the imposed restrictions. |
93 |
|
94 |
I was talking about PRs against portage & repoman. |
95 |
|
96 |
> > > [1]:https://wiki.gentoo.org/wiki/User:MGorny/GLEP:ReqUse |
97 |
> > |
98 |
> > I really don't like the reordering thing. Even the restricted |
99 |
> > syntax does not fix the issue with '^^ ( a b ) b? ( a )' already |
100 |
> > mentioned here. It'd be much better and simpler for the spec just to |
101 |
> > assign a fixed value and use the solving rules with those. |
102 |
> |
103 |
> You're not going to convince me by providing examples that are utterly |
104 |
> broken by design and meaningless ;-). |
105 |
|
106 |
Well... if it's so obvious that the example is broken by design that |
107 |
you don't even bother to explain why, I assume you have an algorithm for |
108 |
that. Where is the code ? What are the numbers ? How many ebuilds might |
109 |
fail after reordering ? How can this be improved ? |
110 |
|
111 |
Extra question: Is there *really* a point in pushing user preferences |
112 |
that way, esp. when developers can write '!b? ( a )' instead of '|| ( a |
113 |
b )' and just kill any possibility of changing the order ? |
114 |
|
115 |
As for a real world example, I'll let you find some more interesting |
116 |
ones, but this one will probably be interesting to you and is a |
117 |
good start: |
118 |
|
119 |
app-text/wklej-0.2.1-r1 ^^ ( python_single_target_pypy |
120 |
python_single_target_pypy3 python_single_target_python2_7 |
121 |
python_single_target_python3_4 python_single_target_python3_5 |
122 |
python_single_target_python3_6 ) python_single_target_pypy? |
123 |
( python_targets_pypy ) python_single_target_pypy3? |
124 |
( python_targets_pypy3 ) python_single_target_python2_7? |
125 |
( python_targets_python2_7 ) python_single_target_python3_4? |
126 |
( python_targets_python3_4 ) python_single_target_python3_5? |
127 |
( python_targets_python3_5 ) python_single_target_python3_6? |
128 |
( python_targets_python3_6 ) vim? ( ^^ ( python_single_target_python2_7 |
129 |
) ) |
130 |
|
131 |
|
132 |
Hint: It loops as written here. Reordering the ^^ in a proper way makes |
133 |
it solvable. Putting the 'vim? ( ... )' part first makes it solvable in |
134 |
one pass. |
135 |
|
136 |
Extra bonus: If your algorithm solves that in reasonable time, |
137 |
run it again as if PYTHON_COMPAT also contained |
138 |
'python3_{7,8,9,10,11,12}' |
139 |
|
140 |
Alexis. |