Mercurial > hg
changeset 34046:f23cbca9b277
revsetlang: match tree by helper function on optimize
This should make optimize() more readable and less error-prone, but it doubles
the parsing cost.
(original)
$ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
'L.optimize(L.analyze(L.parse("ancestors(x) and not ancestors(y)")))'
10000 loops, best of 3: 79.3 usec per loop
(this patch)
$ python -m timeit -n10000 -s 'from mercurial import revsetlang as L' \
'L._treecache.clear(); \
L.optimize(L.analyze(L.parse("ancestors(x) and not ancestors(y)")))'
10000 loops, best of 3: 201 usec per loop
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Wed, 17 Feb 2016 21:40:59 +0900 |
parents | 79681d8ee587 |
children | b2c691d75d93 |
files | mercurial/revsetlang.py |
diffstat | 1 files changed, 17 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revsetlang.py Wed Feb 17 21:31:09 2016 +0900 +++ b/mercurial/revsetlang.py Wed Feb 17 21:40:59 2016 +0900 @@ -258,6 +258,18 @@ template = _cachedtree(tmplspec) return parser.buildtree(template, ('symbol', '_'), *repls) +def _match(patspec, tree): + """Test if a tree matches the given pattern statement; return the matches + + >>> _match('f(_)', parse('f()')) + >>> _match('f(_)', parse('f(1)')) + [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')] + >>> _match('f(_)', parse('f(1, 2)')) + """ + pattern = _cachedtree(patspec) + return parser.matchtree(pattern, tree, ('symbol', '_'), + {'keyvalue', 'list'}) + def _isnamedfunc(x, funcname): """Check if given tree matches named function""" return x and x[0] == 'func' and getsymbol(x[1]) == funcname @@ -278,15 +290,7 @@ return x[2] def _matchonly(revs, bases): - """ - >>> f = lambda *args: _matchonly(*map(parse, args)) - >>> f('ancestors(A)', 'not ancestors(B)') - ('list', ('symbol', 'A'), ('symbol', 'B')) - """ - ta = _matchnamedfunc(revs, 'ancestors') - tb = bases and bases[0] == 'not' and _matchnamedfunc(bases[1], 'ancestors') - if _isposargs(ta, 1) and _isposargs(tb, 1): - return ('list', ta, tb) + return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases)) def _fixops(x): """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be @@ -389,8 +393,9 @@ if m: return w, _build('only(_, _)', *m[1:]) - if tb is not None and tb[0] == 'not': - return wa, ('difference', ta, tb[1]) + m = _match('not _', tb) + if m: + return wa, ('difference', ta, m[1]) if wa > wb: op = 'andsmally' return w, (op, ta, tb) @@ -424,7 +429,7 @@ 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): + if _match('public()', x[1]): o = _optimize(_build('_notpublic()'), not small) return o[0], o[1] else: