mercurial/revsetlang.py
changeset 41222 8aca89a694d4
parent 41221 73203cdfe3fe
child 41239 26b0a7514f01
equal deleted inserted replaced
41221:73203cdfe3fe 41222:8aca89a694d4
   331     elif op == 'dagrangepost':
   331     elif op == 'dagrangepost':
   332         return _analyze(_build('descendants(_)', x[1]))
   332         return _analyze(_build('descendants(_)', x[1]))
   333     elif op == 'negate':
   333     elif op == 'negate':
   334         s = getstring(x[1], _("can't negate that"))
   334         s = getstring(x[1], _("can't negate that"))
   335         return _analyze(('string', '-' + s))
   335         return _analyze(('string', '-' + s))
   336     elif op in ('string', 'symbol'):
   336     elif op in ('string', 'symbol', 'smartset'):
   337         return x
   337         return x
   338     elif op == 'rangeall':
   338     elif op == 'rangeall':
   339         return (op, None)
   339         return (op, None)
   340     elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}:
   340     elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}:
   341         return (op, _analyze(x[1]))
   341         return (op, _analyze(x[1]))
   371 def _optimize(x):
   371 def _optimize(x):
   372     if x is None:
   372     if x is None:
   373         return 0, x
   373         return 0, x
   374 
   374 
   375     op = x[0]
   375     op = x[0]
   376     if op in ('string', 'symbol'):
   376     if op in ('string', 'symbol', 'smartset'):
   377         return 0.5, x # single revisions are small
   377         return 0.5, x # single revisions are small
   378     elif op == 'and':
   378     elif op == 'and':
   379         wa, ta = _optimize(x[1])
   379         wa, ta = _optimize(x[1])
   380         wb, tb = _optimize(x[2])
   380         wb, tb = _optimize(x[2])
   381         w = min(wa, wb)
   381         w = min(wa, wb)
   533     return tree
   533     return tree
   534 
   534 
   535 def foldconcat(tree):
   535 def foldconcat(tree):
   536     """Fold elements to be concatenated by `##`
   536     """Fold elements to be concatenated by `##`
   537     """
   537     """
   538     if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
   538     if (not isinstance(tree, tuple)
       
   539         or tree[0] in ('string', 'symbol', 'smartset')):
   539         return tree
   540         return tree
   540     if tree[0] == '_concat':
   541     if tree[0] == '_concat':
   541         pending = [tree]
   542         pending = [tree]
   542         l = []
   543         l = []
   543         while pending:
   544         while pending:
   688                 arg = sorted(arg)
   689                 arg = sorted(arg)
   689             ret.append(_formatintlist(list(arg)))
   690             ret.append(_formatintlist(list(arg)))
   690         else:
   691         else:
   691             raise error.ProgrammingError("unknown revspec item type: %r" % t)
   692             raise error.ProgrammingError("unknown revspec item type: %r" % t)
   692     return b''.join(ret)
   693     return b''.join(ret)
       
   694 
       
   695 def spectree(expr, *args):
       
   696     """similar to formatspec but return a parsed and optimized tree"""
       
   697     parsed = _parseargs(expr, args)
       
   698     ret = []
       
   699     inputs = []
       
   700     for t, arg in parsed:
       
   701         if t is None:
       
   702             ret.append(arg)
       
   703         elif t == 'baseset':
       
   704             newtree = ('smartset', smartset.baseset(arg))
       
   705             inputs.append(newtree)
       
   706             ret.append("$")
       
   707         else:
       
   708             raise error.ProgrammingError("unknown revspec item type: %r" % t)
       
   709     expr = b''.join(ret)
       
   710     tree = _parsewith(expr, syminitletters=_aliassyminitletters)
       
   711     tree = parser.buildtree(tree, ('symbol', '$'), *inputs)
       
   712     tree = foldconcat(tree)
       
   713     tree = analyze(tree)
       
   714     tree = optimize(tree)
       
   715     return tree
   693 
   716 
   694 def _parseargs(expr, args):
   717 def _parseargs(expr, args):
   695     """parse the expression and replace all inexpensive args
   718     """parse the expression and replace all inexpensive args
   696 
   719 
   697     return a list of tuple [(arg-type, arg-value)]
   720     return a list of tuple [(arg-type, arg-value)]