mercurial/revset.py
changeset 29904 e4b4168a4f1c
parent 29898 7203400f91b0
child 29905 371c2a39eead
equal deleted inserted replaced
29903:fe81c953f369 29904:e4b4168a4f1c
  2340         elif x[2][0] == 'rangeall':
  2340         elif x[2][0] == 'rangeall':
  2341             return _fixops(('rangepost', post))
  2341             return _fixops(('rangepost', post))
  2342 
  2342 
  2343     return (op,) + tuple(_fixops(y) for y in x[1:])
  2343     return (op,) + tuple(_fixops(y) for y in x[1:])
  2344 
  2344 
       
  2345 def _analyze(x):
       
  2346     """Transform raw parsed tree to evaluatable tree which can be fed to
       
  2347     optimize() or getset()
       
  2348 
       
  2349     All pseudo operations should be mapped to real operations or functions
       
  2350     defined in methods or symbols table respectively.
       
  2351     """
       
  2352     if x is None:
       
  2353         return x
       
  2354 
       
  2355     op = x[0]
       
  2356     if op == 'minus':
       
  2357         return _analyze(('and', x[1], ('not', x[2])))
       
  2358     elif op == 'only':
       
  2359         t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
       
  2360         return _analyze(t)
       
  2361     elif op == 'onlypost':
       
  2362         return _analyze(('func', ('symbol', 'only'), x[1]))
       
  2363     elif op == 'dagrangepre':
       
  2364         return _analyze(('func', ('symbol', 'ancestors'), x[1]))
       
  2365     elif op == 'dagrangepost':
       
  2366         return _analyze(('func', ('symbol', 'descendants'), x[1]))
       
  2367     elif op == 'rangeall':
       
  2368         return _analyze(('range', ('string', '0'), ('string', 'tip')))
       
  2369     elif op == 'rangepre':
       
  2370         return _analyze(('range', ('string', '0'), x[1]))
       
  2371     elif op == 'rangepost':
       
  2372         return _analyze(('range', x[1], ('string', 'tip')))
       
  2373     elif op == 'negate':
       
  2374         s = getstring(x[1], _("can't negate that"))
       
  2375         return _analyze(('string', '-' + s))
       
  2376     elif op in ('string', 'symbol'):
       
  2377         return x
       
  2378     elif op == 'and':
       
  2379         ta = _analyze(x[1])
       
  2380         tb = _analyze(x[2])
       
  2381         return (op, ta, tb)
       
  2382     elif op == 'or':
       
  2383         return (op,) + tuple(_analyze(y) for y in x[1:])
       
  2384     elif op == 'not':
       
  2385         return (op, _analyze(x[1]))
       
  2386     elif op == 'parentpost':
       
  2387         return (op, _analyze(x[1]))
       
  2388     elif op == 'group':
       
  2389         return _analyze(x[1])
       
  2390     elif op in ('dagrange', 'range', 'parent', 'ancestor'):
       
  2391         ta = _analyze(x[1])
       
  2392         tb = _analyze(x[2])
       
  2393         return (op, ta, tb)
       
  2394     elif op == 'list':
       
  2395         return (op,) + tuple(_analyze(y) for y in x[1:])
       
  2396     elif op == 'keyvalue':
       
  2397         return (op, x[1], _analyze(x[2]))
       
  2398     elif op == 'func':
       
  2399         return (op, x[1], _analyze(x[2]))
       
  2400     raise ValueError('invalid operator %r' % op)
       
  2401 
  2345 def _optimize(x, small):
  2402 def _optimize(x, small):
       
  2403     """Optimize evaluatable tree
       
  2404 
       
  2405     All pseudo operations should be transformed beforehand.
       
  2406     """
  2346     if x is None:
  2407     if x is None:
  2347         return 0, x
  2408         return 0, x
  2348 
  2409 
  2349     smallbonus = 1
  2410     smallbonus = 1
  2350     if small:
  2411     if small:
  2351         smallbonus = .5
  2412         smallbonus = .5
  2352 
  2413 
  2353     op = x[0]
  2414     op = x[0]
  2354     if op == 'minus':
  2415     if op in ('string', 'symbol'):
  2355         return _optimize(('and', x[1], ('not', x[2])), small)
       
  2356     elif op == 'only':
       
  2357         t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
       
  2358         return _optimize(t, small)
       
  2359     elif op == 'onlypost':
       
  2360         return _optimize(('func', ('symbol', 'only'), x[1]), small)
       
  2361     elif op == 'dagrangepre':
       
  2362         return _optimize(('func', ('symbol', 'ancestors'), x[1]), small)
       
  2363     elif op == 'dagrangepost':
       
  2364         return _optimize(('func', ('symbol', 'descendants'), x[1]), small)
       
  2365     elif op == 'rangeall':
       
  2366         return _optimize(('range', ('string', '0'), ('string', 'tip')), small)
       
  2367     elif op == 'rangepre':
       
  2368         return _optimize(('range', ('string', '0'), x[1]), small)
       
  2369     elif op == 'rangepost':
       
  2370         return _optimize(('range', x[1], ('string', 'tip')), small)
       
  2371     elif op == 'negate':
       
  2372         s = getstring(x[1], _("can't negate that"))
       
  2373         return _optimize(('string', '-' + s), small)
       
  2374     elif op in ('string', 'symbol'):
       
  2375         return smallbonus, x # single revisions are small
  2416         return smallbonus, x # single revisions are small
  2376     elif op == 'and':
  2417     elif op == 'and':
  2377         wa, ta = _optimize(x[1], True)
  2418         wa, ta = _optimize(x[1], True)
  2378         wb, tb = _optimize(x[2], True)
  2419         wb, tb = _optimize(x[2], True)
  2379         w = min(wa, wb)
  2420         w = min(wa, wb)
  2430             o = _optimize(x[1], not small)
  2471             o = _optimize(x[1], not small)
  2431             return o[0], (op, o[1])
  2472             return o[0], (op, o[1])
  2432     elif op == 'parentpost':
  2473     elif op == 'parentpost':
  2433         o = _optimize(x[1], small)
  2474         o = _optimize(x[1], small)
  2434         return o[0], (op, o[1])
  2475         return o[0], (op, o[1])
  2435     elif op == 'group':
       
  2436         return _optimize(x[1], small)
       
  2437     elif op in ('dagrange', 'range', 'parent', 'ancestor'):
  2476     elif op in ('dagrange', 'range', 'parent', 'ancestor'):
  2438         wa, ta = _optimize(x[1], small)
  2477         wa, ta = _optimize(x[1], small)
  2439         wb, tb = _optimize(x[2], small)
  2478         wb, tb = _optimize(x[2], small)
  2440         return wa + wb, (op, ta, tb)
  2479         return wa + wb, (op, ta, tb)
  2441     elif op == 'list':
  2480     elif op == 'list':
  2464             w = 1
  2503             w = 1
  2465         return w + wa, (op, x[1], ta)
  2504         return w + wa, (op, x[1], ta)
  2466     raise ValueError('invalid operator %r' % op)
  2505     raise ValueError('invalid operator %r' % op)
  2467 
  2506 
  2468 def optimize(tree):
  2507 def optimize(tree):
       
  2508     tree = _analyze(tree)
  2469     _weight, newtree = _optimize(tree, small=True)
  2509     _weight, newtree = _optimize(tree, small=True)
  2470     return newtree
  2510     return newtree
  2471 
  2511 
  2472 # the set of valid characters for the initial letter of symbols in
  2512 # the set of valid characters for the initial letter of symbols in
  2473 # alias declarations and definitions
  2513 # alias declarations and definitions