mercurial/revsetlang.py
changeset 34046 f23cbca9b277
parent 34044 b862e6fca7ac
child 34047 b2c691d75d93
equal deleted inserted replaced
34045:79681d8ee587 34046:f23cbca9b277
   256     ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
   256     ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2'))
   257     """
   257     """
   258     template = _cachedtree(tmplspec)
   258     template = _cachedtree(tmplspec)
   259     return parser.buildtree(template, ('symbol', '_'), *repls)
   259     return parser.buildtree(template, ('symbol', '_'), *repls)
   260 
   260 
       
   261 def _match(patspec, tree):
       
   262     """Test if a tree matches the given pattern statement; return the matches
       
   263 
       
   264     >>> _match('f(_)', parse('f()'))
       
   265     >>> _match('f(_)', parse('f(1)'))
       
   266     [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')]
       
   267     >>> _match('f(_)', parse('f(1, 2)'))
       
   268     """
       
   269     pattern = _cachedtree(patspec)
       
   270     return parser.matchtree(pattern, tree, ('symbol', '_'),
       
   271                             {'keyvalue', 'list'})
       
   272 
   261 def _isnamedfunc(x, funcname):
   273 def _isnamedfunc(x, funcname):
   262     """Check if given tree matches named function"""
   274     """Check if given tree matches named function"""
   263     return x and x[0] == 'func' and getsymbol(x[1]) == funcname
   275     return x and x[0] == 'func' and getsymbol(x[1]) == funcname
   264 
   276 
   265 def _isposargs(x, n):
   277 def _isposargs(x, n):
   276     if not _isnamedfunc(x, funcname):
   288     if not _isnamedfunc(x, funcname):
   277         return
   289         return
   278     return x[2]
   290     return x[2]
   279 
   291 
   280 def _matchonly(revs, bases):
   292 def _matchonly(revs, bases):
   281     """
   293     return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases))
   282     >>> f = lambda *args: _matchonly(*map(parse, args))
       
   283     >>> f('ancestors(A)', 'not ancestors(B)')
       
   284     ('list', ('symbol', 'A'), ('symbol', 'B'))
       
   285     """
       
   286     ta = _matchnamedfunc(revs, 'ancestors')
       
   287     tb = bases and bases[0] == 'not' and _matchnamedfunc(bases[1], 'ancestors')
       
   288     if _isposargs(ta, 1) and _isposargs(tb, 1):
       
   289         return ('list', ta, tb)
       
   290 
   294 
   291 def _fixops(x):
   295 def _fixops(x):
   292     """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
   296     """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be
   293     handled well by our simple top-down parser"""
   297     handled well by our simple top-down parser"""
   294     if not isinstance(x, tuple):
   298     if not isinstance(x, tuple):
   387         # (::x and not ::y)/(not ::y and ::x) have a fast path
   391         # (::x and not ::y)/(not ::y and ::x) have a fast path
   388         m = _matchonly(ta, tb) or _matchonly(tb, ta)
   392         m = _matchonly(ta, tb) or _matchonly(tb, ta)
   389         if m:
   393         if m:
   390             return w, _build('only(_, _)', *m[1:])
   394             return w, _build('only(_, _)', *m[1:])
   391 
   395 
   392         if tb is not None and tb[0] == 'not':
   396         m = _match('not _', tb)
   393             return wa, ('difference', ta, tb[1])
   397         if m:
       
   398             return wa, ('difference', ta, m[1])
   394         if wa > wb:
   399         if wa > wb:
   395             op = 'andsmally'
   400             op = 'andsmally'
   396         return w, (op, ta, tb)
   401         return w, (op, ta, tb)
   397     elif op == 'or':
   402     elif op == 'or':
   398         # fast path for machine-generated expression, that is likely to have
   403         # fast path for machine-generated expression, that is likely to have
   422         if len(ts) == 1:
   427         if len(ts) == 1:
   423             return ws[0], ts[0] # 'or' operation is fully optimized out
   428             return ws[0], ts[0] # 'or' operation is fully optimized out
   424         return max(ws), (op, ('list',) + tuple(ts))
   429         return max(ws), (op, ('list',) + tuple(ts))
   425     elif op == 'not':
   430     elif op == 'not':
   426         # Optimize not public() to _notpublic() because we have a fast version
   431         # Optimize not public() to _notpublic() because we have a fast version
   427         if x[1][:3] == ('func', ('symbol', 'public'), None):
   432         if _match('public()', x[1]):
   428             o = _optimize(_build('_notpublic()'), not small)
   433             o = _optimize(_build('_notpublic()'), not small)
   429             return o[0], o[1]
   434             return o[0], o[1]
   430         else:
   435         else:
   431             o = _optimize(x[1], not small)
   436             o = _optimize(x[1], not small)
   432             return o[0], (op, o[1])
   437             return o[0], (op, o[1])