equal
deleted
inserted
replaced
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)] |