diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -7,6 +7,7 @@ from __future__ import absolute_import +import inspect import re from .i18n import _ @@ -52,10 +53,16 @@ # helpers -def getset(repo, subset, x): +def getset(repo, subset, x, order=anyorder): if not x: raise error.ParseError(_("missing argument")) - return methods[x[0]](repo, subset, *x[1:]) + # TODO migrate existing functions to accept "order", and maybe wrap + # registered functions automatically if they do not accept "order". + m = methods[x[0]] + if 'order' in inspect.getargs(m.__code__).args: + return m(repo, subset, *x[1:], order=order) + else: + return m(repo, subset, *x[1:]) def _getrevsource(repo, r): extra = repo[r].extra() @@ -126,27 +133,27 @@ return subset & xs def andset(repo, subset, x, y, order): - return getset(repo, getset(repo, subset, x), y) + return getset(repo, getset(repo, subset, x, order), y, followorder) def differenceset(repo, subset, x, y, order): - return getset(repo, subset, x) - getset(repo, subset, y) + return getset(repo, subset, x, order) - getset(repo, subset, y) -def _orsetlist(repo, subset, xs): +def _orsetlist(repo, subset, xs, order): assert xs if len(xs) == 1: - return getset(repo, subset, xs[0]) + return getset(repo, subset, xs[0], order) p = len(xs) // 2 - a = _orsetlist(repo, subset, xs[:p]) - b = _orsetlist(repo, subset, xs[p:]) + a = _orsetlist(repo, subset, xs[:p], order) + b = _orsetlist(repo, subset, xs[p:], order) return a + b def orset(repo, subset, x, order): xs = getlist(x) if order == followorder: # slow path to take the subset order - return subset & _orsetlist(repo, fullreposet(repo), xs) + return subset & _orsetlist(repo, fullreposet(repo), xs, order) else: - return _orsetlist(repo, subset, xs) + return _orsetlist(repo, subset, xs, order) def notset(repo, subset, x, order): return subset - getset(repo, subset, x) @@ -1124,7 +1131,7 @@ ofs = getinteger(args.get('offset'), _("limit expects a number"), default=0) if ofs < 0: raise error.ParseError(_("negative offset")) - os = getset(repo, fullreposet(repo), args['set']) + os = getset(repo, fullreposet(repo), args['set'], defineorder) ls = os.slice(ofs, ofs + lim) if order == followorder and lim > 1: return subset & ls @@ -1142,7 +1149,7 @@ lim = getinteger(l[1], _("last expects a number")) if lim < 0: raise error.ParseError(_("negative number to select")) - os = getset(repo, fullreposet(repo), l[0]) + os = getset(repo, fullreposet(repo), l[0], defineorder) os.reverse() ls = os.slice(0, lim) if order == followorder and lim > 1: @@ -1508,8 +1515,8 @@ ps.add(parents[1].rev()) return subset & ps -@predicate('present(set)', safe=True) -def present(repo, subset, x): +@predicate('present(set)', safe=True, takeorder=True) +def present(repo, subset, x, order): """An empty set, if any revision in set isn't found; otherwise, all revisions in set. @@ -1518,7 +1525,7 @@ to continue even in such cases. """ try: - return getset(repo, subset, x) + return getset(repo, subset, x, order) except error.RepoLookupError: return baseset() @@ -1718,7 +1725,7 @@ def reverse(repo, subset, x, order): """Reverse order of set. """ - l = getset(repo, subset, x) + l = getset(repo, subset, x, order) if order == defineorder: l.reverse() return l @@ -1802,7 +1809,8 @@ """ s, keyflags, opts = _getsortargs(x) - revs = getset(repo, subset, s) + # Different revs may have a same sort key, so "order" couldn't be "any". + revs = getset(repo, subset, s, order) if not keyflags or order != defineorder: return revs @@ -2113,17 +2121,17 @@ if aliases: tree = revsetlang.expandaliases(tree, aliases, warn=warn) tree = revsetlang.foldconcat(tree) - tree = revsetlang.analyze(tree, order) + tree = revsetlang.analyze(tree) tree = revsetlang.optimize(tree) posttreebuilthook(tree, repo) - return makematcher(tree) + return makematcher(tree, order) -def makematcher(tree): +def makematcher(tree, order=defineorder): """Create a matcher from an evaluatable tree""" def mfunc(repo, subset=None): if subset is None: subset = fullreposet(repo) - return getset(repo, subset, tree) + return getset(repo, subset, tree, order) return mfunc def loadpredicate(ui, extname, registrarobj): diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py --- a/mercurial/revsetlang.py +++ b/mercurial/revsetlang.py @@ -340,78 +340,73 @@ return (op,) + tuple(_fixops(y) for y in x[1:]) -def _analyze(x, order): +def _analyze(x): if x is None: return x op = x[0] if op == 'minus': - return _analyze(('and', x[1], ('not', x[2])), order) + return _analyze(('and', x[1], ('not', x[2]))) elif op == 'only': t = ('func', ('symbol', 'only'), ('list', x[1], x[2])) - return _analyze(t, order) + return _analyze(t) elif op == 'onlypost': - return _analyze(('func', ('symbol', 'only'), x[1]), order) + return _analyze(('func', ('symbol', 'only'), x[1])) elif op == 'dagrangepre': - return _analyze(('func', ('symbol', 'ancestors'), x[1]), order) + return _analyze(('func', ('symbol', 'ancestors'), x[1])) elif op == 'dagrangepost': - return _analyze(('func', ('symbol', 'descendants'), x[1]), order) + return _analyze(('func', ('symbol', 'descendants'), x[1])) elif op == 'negate': s = getstring(x[1], _("can't negate that")) - return _analyze(('string', '-' + s), order) + return _analyze(('string', '-' + s)) elif op in ('string', 'symbol'): return x elif op == 'and': - ta = _analyze(x[1], order) - tb = _analyze(x[2], _tofolloworder[order]) - return (op, ta, tb, order) + ta = _analyze(x[1]) + tb = _analyze(x[2]) + return (op, ta, tb) elif op == 'or': - return (op, _analyze(x[1], order), order) + return (op, _analyze(x[1])) elif op == 'not': - return (op, _analyze(x[1], anyorder), order) + return (op, _analyze(x[1])) elif op == 'rangeall': - return (op, None, order) + return (op, None) elif op in ('rangepre', 'rangepost', 'parentpost'): - return (op, _analyze(x[1], defineorder), order) + return (op, _analyze(x[1])) elif op == 'group': - return _analyze(x[1], order) + return _analyze(x[1]) elif op in ('dagrange', 'range', 'parent', 'ancestor', 'relation', 'subscript'): - ta = _analyze(x[1], defineorder) - tb = _analyze(x[2], defineorder) - return (op, ta, tb, order) + ta = _analyze(x[1]) + tb = _analyze(x[2]) + return (op, ta, tb) elif op == 'relsubscript': - ta = _analyze(x[1], defineorder) - tb = _analyze(x[2], defineorder) - tc = _analyze(x[3], defineorder) - return (op, ta, tb, tc, order) + ta = _analyze(x[1]) + tb = _analyze(x[2]) + tc = _analyze(x[3]) + return (op, ta, tb, tc) elif op == 'list': - return (op,) + tuple(_analyze(y, order) for y in x[1:]) + return (op,) + tuple(_analyze(y) for y in x[1:]) elif op == 'keyvalue': - return (op, x[1], _analyze(x[2], order)) + return (op, x[1], _analyze(x[2])) elif op == 'func': f = getsymbol(x[1]) - d = defineorder - if f == 'present': - # 'present(set)' is known to return the argument set with no - # modification, so forward the current order to its argument - d = order - return (op, x[1], _analyze(x[2], d), order) + return (op, x[1], _analyze(x[2])) raise ValueError('invalid operator %r' % op) -def analyze(x, order=defineorder): +def analyze(x): """Transform raw parsed tree to evaluatable tree which can be fed to optimize() or getset() All pseudo operations should be mapped to real operations or functions defined in methods or symbols table respectively. + """ + return _analyze(x) - 'order' specifies how the current expression 'x' is ordered (see the - constants defined above.) - """ - return _analyze(x, order) - -def _optimize(x, small): +def _optimize(x, small, preserveorder=False): + # preserveorder: when set to True, certain optimization that may break + # ordering will be skipped. For example, "or" and "and" list will have + # their arguments order preserved. if x is None: return 0, x @@ -423,26 +418,24 @@ if op in ('string', 'symbol'): return smallbonus, x # single revisions are small elif op == 'and': - wa, ta = _optimize(x[1], True) + wa, ta = _optimize(x[1], True, preserveorder=preserveorder) wb, tb = _optimize(x[2], True) - order = x[3] w = min(wa, wb) # (::x and not ::y)/(not ::y and ::x) have a fast path tm = _matchonly(ta, tb) or _matchonly(tb, ta) if tm: - return w, ('func', ('symbol', 'only'), tm, order) + return w, ('func', ('symbol', 'only'), tm) if tb is not None and tb[0] == 'not': - return wa, ('difference', ta, tb[1], order) + return wa, ('difference', ta, tb[1]) - if wa > wb: - return w, (op, tb, ta, order) - return w, (op, ta, tb, order) + if not preserveorder and wa > wb: + return w, (op, tb, ta) + return w, (op, ta, tb) elif op == 'or': # fast path for machine-generated expression, that is likely to have # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()' - order = x[2] ws, ts, ss = [], [], [] def flushss(): if not ss: @@ -451,13 +444,13 @@ w, t = ss[0] else: s = '\0'.join(t[1] for w, t in ss) - y = ('func', ('symbol', '_list'), ('string', s), order) - w, t = _optimize(y, False) + y = ('func', ('symbol', '_list'), ('string', s)) + w, t = _optimize(y, False, preserveorder=preserveorder) ws.append(w) ts.append(t) del ss[:] for y in getlist(x[1]): - w, t = _optimize(y, False) + w, t = _optimize(y, False, preserveorder=preserveorder) if t is not None and (t[0] == 'string' or t[0] == 'symbol'): ss.append((w, t)) continue @@ -467,40 +460,34 @@ flushss() if len(ts) == 1: return ws[0], ts[0] # 'or' operation is fully optimized out - if order != defineorder: + if not preserveorder: # reorder by weight only when f(a + b) == f(b + a) ts = [wt[1] for wt in sorted(zip(ws, ts), key=lambda wt: wt[0])] - return max(ws), (op, ('list',) + tuple(ts), order) + return max(ws), (op, ('list',) + tuple(ts)) elif op == 'not': # Optimize not public() to _notpublic() because we have a fast version if x[1][:3] == ('func', ('symbol', 'public'), None): - order = x[1][3] - newsym = ('func', ('symbol', '_notpublic'), None, order) + newsym = ('func', ('symbol', '_notpublic'), None) o = _optimize(newsym, not small) return o[0], o[1] else: o = _optimize(x[1], not small) - order = x[2] - return o[0], (op, o[1], order) + return o[0], (op, o[1]) elif op == 'rangeall': return smallbonus, x elif op in ('rangepre', 'rangepost', 'parentpost'): o = _optimize(x[1], small) - order = x[2] - return o[0], (op, o[1], order) + return o[0], (op, o[1]) elif op in ('dagrange', 'range'): wa, ta = _optimize(x[1], small) wb, tb = _optimize(x[2], small) - order = x[3] - return wa + wb, (op, ta, tb, order) + return wa + wb, (op, ta, tb) elif op in ('parent', 'ancestor', 'relation', 'subscript'): w, t = _optimize(x[1], small) - order = x[3] - return w, (op, t, x[2], order) + return w, (op, t, x[2]) elif op == 'relsubscript': w, t = _optimize(x[1], small) - order = x[4] - return w, (op, t, x[2], x[3], order) + return w, (op, t, x[2], x[3]) elif op == 'list': ws, ts = zip(*(_optimize(y, small) for y in x[1:])) return sum(ws), (op,) + ts @@ -509,7 +496,7 @@ return w, (op, x[1], t) elif op == 'func': f = getsymbol(x[1]) - wa, ta = _optimize(x[2], small) + wa, ta = _optimize(x[2], small, True) if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep', 'keyword', 'outgoing', 'user', 'destination'): w = 10 # slow @@ -525,8 +512,7 @@ w = 10 # assume most sorts look at changelog else: w = 1 - order = x[3] - return w + wa, (op, x[1], ta, order) + return w + wa, (op, x[1], ta) raise ValueError('invalid operator %r' % op) def optimize(tree): @@ -534,7 +520,7 @@ All pseudo operations should be transformed beforehand. """ - _weight, newtree = _optimize(tree, small=True) + _weight, newtree = _optimize(tree, small=True, preserveorder=True) return newtree # the set of valid characters for the initial letter of symbols in diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -166,8 +166,7 @@ None) * optimized: (rangeall - None - define) + None) * set: 0 @@ -495,8 +494,7 @@ ('symbol', 'foo') (func ('symbol', '_notpublic') - None - any)) + None)) hg: parse error: can't use a key-value pair in this context [255] @@ -538,21 +536,16 @@ (not (func ('symbol', 'public') - None - any) - define) + None)) ('symbol', 'generations') - ('symbol', '0') - define) + ('symbol', '0')) * optimized: (relsubscript (func ('symbol', '_notpublic') - None - any) + None) ('symbol', 'generations') - ('symbol', '0') - define) + ('symbol', '0')) resolution of subscript and relation-subscript ternary operators: @@ -560,8 +553,7 @@ * analyzed: (subscript ('symbol', 'tip') - ('symbol', '0') - define) + ('symbol', '0')) hg: parse error: can't use a subscript in this context [255] @@ -570,8 +562,7 @@ (relsubscript ('symbol', 'tip') ('symbol', 'rel') - ('symbol', '0') - define) + ('symbol', '0')) hg: parse error: unknown identifier: rel [255] @@ -580,10 +571,8 @@ (subscript (relation ('symbol', 'tip') - ('symbol', 'rel') - define) - ('symbol', '0') - define) + ('symbol', 'rel')) + ('symbol', '0')) hg: parse error: can't use a subscript in this context [255] @@ -593,10 +582,8 @@ (relsubscript ('symbol', 'tip') ('symbol', 'rel') - ('symbol', '0') - define) - ('symbol', '1') - define) + ('symbol', '0')) + ('symbol', '1')) hg: parse error: can't use a subscript in this context [255] @@ -605,11 +592,9 @@ (relsubscript (relation ('symbol', 'tip') - ('symbol', 'rel0') - define) + ('symbol', 'rel0')) ('symbol', 'rel1') - ('symbol', '1') - define) + ('symbol', '1')) hg: parse error: unknown identifier: rel1 [255] @@ -619,11 +604,9 @@ (relsubscript ('symbol', 'tip') ('symbol', 'rel0') - ('symbol', '0') - define) + ('symbol', '0')) ('symbol', 'rel1') - ('symbol', '1') - define) + ('symbol', '1')) hg: parse error: unknown identifier: rel1 [255] @@ -700,20 +683,15 @@ (or (list ('symbol', '0') - ('symbol', '1')) - define) + ('symbol', '1'))) (not - ('symbol', '1') - follow) - define) + ('symbol', '1'))) * optimized: (difference (func ('symbol', '_list') - ('string', '0\x001') - define) - ('symbol', '1') - define) + ('string', '0\x001')) + ('symbol', '1')) 0 $ hg debugrevspec -p unknown '0' @@ -733,27 +711,18 @@ (and (func ('symbol', 'r3232') - None - define) - ('symbol', '2') - define) + None) + ('symbol', '2')) * optimized: (and - ('symbol', '2') (func ('symbol', 'r3232') - None - define) - define) + None) + ('symbol', '2')) * analyzed set: * optimized set: - - --- analyzed - +++ optimized - 2 - +2 - [1] + $ hg debugrevspec --no-optimized --verify-optimized '0' abort: cannot use --verify-optimized with --no-optimized @@ -776,8 +745,7 @@ None) * analyzed: (rangeall - None - define) + None) * set: 0 @@ -793,8 +761,7 @@ $ try -p analyzed ':1' * analyzed: (rangepre - ('symbol', '1') - define) + ('symbol', '1')) * set: 0 @@ -805,9 +772,7 @@ (or (list ('symbol', '1') - ('symbol', '2')) - define) - define) + ('symbol', '2')))) * set: 0 @@ -818,9 +783,7 @@ (rangepre (and ('symbol', '1') - ('symbol', '2') - define) - define) + ('symbol', '2'))) * set: @@ -1643,11 +1606,8 @@ (difference (range ('symbol', '8') - ('symbol', '9') - define) - ('symbol', '8') - define) - define) + ('symbol', '9')) + ('symbol', '8'))) * set: 8 @@ -1663,8 +1623,7 @@ ('symbol', 'only') (list ('symbol', '9') - ('symbol', '5')) - define) + ('symbol', '5'))) * set: 2 @@ -1999,18 +1958,13 @@ (and (range ('symbol', '3') - ('symbol', '0') - define) + ('symbol', '0')) (range ('symbol', '0') - ('symbol', '3') - follow) - define) + ('symbol', '3'))) (range ('symbol', '2') - ('symbol', '1') - any) - define) + ('symbol', '1'))) * set: , @@ -2072,17 +2023,13 @@ (and (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (or (list ('symbol', '2') (range ('symbol', '0') - ('symbol', '1') - follow)) - follow) - define) + ('symbol', '1'))))) * set: , @@ -2105,19 +2052,16 @@ ('string', '0\x001\x002'))) * optimized: (and + (range + ('symbol', '2') + ('symbol', '0')) (func ('symbol', '_intlist') - ('string', '0\x001\x002') - follow) - (range - ('symbol', '2') - ('symbol', '0') - define) - define) + ('string', '0\x001\x002'))) * set: , - > + > 2 1 0 @@ -2134,13 +2078,10 @@ (and (func ('symbol', '_intlist') - ('string', '0\x002\x001') - define) + ('string', '0\x002\x001')) (range ('symbol', '2') - ('symbol', '0') - follow) - define) + ('symbol', '0'))) * set: , @@ -2163,13 +2104,10 @@ (and (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (func ('symbol', '_hexlist') - ('string', '*') (glob) - follow) - define) + ('string', '2785f51eece5a23075c6f1d74702d8d9cb8bf0d4\x00d75937da8da0322d18c3771fb029ffd88b996c89\x005ed5505e9f1c21de2345daabdd7913fe53e4acd2'))) * set: , @@ -2188,17 +2126,16 @@ ('symbol', '0'))) * optimized: (and - (range - ('symbol', '2') - ('symbol', '0') - follow) (func ('symbol', '_hexlist') - ('string', '*') (glob) - define) - define) + ('string', '2785f51eece5a23075c6f1d74702d8d9cb8bf0d4\x005ed5505e9f1c21de2345daabdd7913fe53e4acd2\x00d75937da8da0322d18c3771fb029ffd88b996c89')) + (range + ('symbol', '2') + ('symbol', '0'))) * set: - + , + > 0 2 1 @@ -2211,13 +2148,10 @@ (difference (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (func ('symbol', '_list') - ('string', '0\x001') - any) - define) + ('string', '0\x001'))) * set: , @@ -2230,24 +2164,21 @@ (difference (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (and (range ('symbol', '0') - ('symbol', '2') - any) + ('symbol', '2')) (func ('symbol', '_list') - ('string', '0\x001') - any) - any) - define) + ('string', '0\x001')))) * set: , >> + , + >>> 2 because 'present()' does nothing other than suppressing an error, the @@ -2259,9 +2190,7 @@ ('symbol', 'present') (func ('symbol', '_list') - ('string', '2\x000\x001') - define) - define) + ('string', '2\x000\x001'))) * set: 2 @@ -2284,16 +2213,12 @@ (and (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (func ('symbol', 'present') (func ('symbol', '_list') - ('string', '0\x001\x002') - follow) - follow) - define) + ('string', '0\x001\x002')))) * set: , @@ -2318,16 +2243,12 @@ (and (range ('symbol', '0') - ('symbol', '2') - define) + ('symbol', '2')) (func ('symbol', 'reverse') (func ('symbol', 'all') - None - define) - follow) - define) + None))) * set: , @@ -2355,18 +2276,14 @@ (and (range ('symbol', '0') - ('symbol', '2') - define) + ('symbol', '2')) (func ('symbol', 'sort') (list (func ('symbol', 'all') - None - define) - ('string', '-rev')) - follow) - define) + None) + ('string', '-rev')))) * set: , @@ -2402,16 +2319,12 @@ (and (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (func ('symbol', 'first') (func ('symbol', '_list') - ('string', '1\x000\x002') - define) - follow) - define) + ('string', '1\x000\x002')))) * set: , @@ -2435,16 +2348,12 @@ (difference (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (func ('symbol', 'last') (func ('symbol', '_list') - ('string', '0\x002\x001') - define) - any) - define) + ('string', '0\x002\x001')))) * set: , @@ -2477,19 +2386,14 @@ (and (range ('symbol', '2') - ('symbol', '0') - define) + ('symbol', '0')) (range (func ('symbol', '_list') - ('string', '1\x000\x002') - define) + ('string', '1\x000\x002')) (func ('symbol', '_list') - ('string', '0\x002\x001') - define) - follow) - define) + ('string', '0\x002\x001')))) * set: , @@ -2515,18 +2419,17 @@ * optimized: (and (func - ('symbol', '_list') - ('string', '2\x000\x001') - follow) + ('symbol', 'contains') + ('string', 'glob:*')) (func - ('symbol', 'contains') - ('string', 'glob:*') - define) - define) + ('symbol', '_list') + ('string', '2\x000\x001'))) * set: , - > + , + >, + > 0 1 2 @@ -2550,21 +2453,19 @@ * optimized: (and (func - ('symbol', '_list') - ('string', '0\x002\x001') - follow) - (func ('symbol', 'reverse') (func ('symbol', 'contains') - ('string', 'glob:*') - define) - define) - define) + ('string', 'glob:*'))) + (func + ('symbol', '_list') + ('string', '0\x002\x001'))) * set: , - > + , + >, + > 2 1 0 @@ -2577,8 +2478,7 @@ (and (range ('symbol', '0') - ('symbol', '2') - define) + ('symbol', '2')) (or (list ('symbol', '2') @@ -2586,11 +2486,7 @@ ('symbol', 'reverse') (func ('symbol', 'contains') - ('string', 'a') - define) - follow)) - follow) - define) + ('string', 'a')))))) * set: , @@ -2606,28 +2502,25 @@ $ try -p optimized '(reverse(contains("a")) + 2) & 0:2' * optimized: (and - (range - ('symbol', '0') - ('symbol', '2') - follow) (or (list (func ('symbol', 'reverse') (func ('symbol', 'contains') - ('string', 'a') - define) - define) - ('symbol', '2')) - define) - define) + ('string', 'a'))) + ('symbol', '2'))) + (range + ('symbol', '0') + ('symbol', '2'))) * set: - , - >, - > + , + >, + >, + > 1 0 2 @@ -3016,8 +2909,7 @@ * optimized: (func ('symbol', '_list') - ('string', '0\x001\x002\x00-2\x00tip\x00null') - define) + ('string', '0\x001\x002\x00-2\x00tip\x00null')) * set: 0 @@ -3040,13 +2932,10 @@ (list (func ('symbol', '_list') - ('string', '0\x001') - define) + ('string', '0\x001')) (range ('symbol', '2') - ('symbol', '3') - define)) - define) + ('symbol', '3')))) * set: , @@ -3073,18 +2962,14 @@ (list (range ('symbol', '0') - ('symbol', '1') - define) + ('symbol', '1')) ('symbol', '2') (range ('symbol', '3') - ('symbol', '4') - define) + ('symbol', '4')) (func ('symbol', '_list') - ('string', '5\x006') - define)) - define) + ('string', '5\x006')))) * set: 3 @@ -3281,8 +3163,7 @@ ('symbol', 'only') (list ('symbol', '1') - ('symbol', '3')) - define) + ('symbol', '3'))) * set: $ try --optimize 'not ::2 and ::6' @@ -3297,8 +3178,7 @@ ('symbol', 'only') (list ('symbol', '6') - ('symbol', '2')) - define) + ('symbol', '2'))) * set: 3 @@ -3319,8 +3199,7 @@ ('symbol', 'only') (list ('symbol', '6') - ('symbol', '4')) - define) + ('symbol', '4'))) * set: 3 @@ -3337,12 +3216,10 @@ None)) * optimized: (and - None (func ('symbol', 'ancestors') - ('symbol', '1') - define) - define) + ('symbol', '1')) + None) hg: parse error: missing argument [255] @@ -3353,15 +3230,12 @@ (difference (func ('symbol', 'ancestors') - ('symbol', '6') - define) + ('symbol', '6')) (func ('symbol', 'ancestors') (list ('symbol', '4') - ('symbol', '1')) - any) - define) + ('symbol', '1')))) 0 1 3 @@ -3374,13 +3248,10 @@ ('symbol', 'ancestors') (list ('symbol', '6') - ('symbol', '1')) - define) + ('symbol', '1'))) (func ('symbol', 'ancestors') - ('symbol', '4') - any) - define) + ('symbol', '4'))) 5 6 @@ -3394,15 +3265,12 @@ ('symbol', 'ancestors') (keyvalue ('symbol', 'set') - ('symbol', '6')) - define) + ('symbol', '6'))) (func ('symbol', 'ancestors') (keyvalue ('symbol', 'set') - ('symbol', '4')) - any) - define) + ('symbol', '4')))) 3 5 6