comparison mercurial/revset.py @ 29933:b3845cab4ddc

revset: wrap arguments of 'or' by 'list' node This makes the number of 'or' arguments deterministic so we can attach additional ordering flag to all operator nodes. See the next patch. We rewrite the tree immediately after chained 'or' operations are flattened by simplifyinfixops(), so we don't need to care if arguments are stored in x[1] or x[1:].
author Yuya Nishihara <yuya@tcha.org>
date Sun, 07 Aug 2016 17:04:05 +0900
parents ae933e3e2226
children 90455e7bf543
comparison
equal deleted inserted replaced
29932:e5a97ec6ebb8 29933:b3845cab4ddc
395 return getset(repo, getset(repo, subset, x), y) 395 return getset(repo, getset(repo, subset, x), y)
396 396
397 def differenceset(repo, subset, x, y): 397 def differenceset(repo, subset, x, y):
398 return getset(repo, subset, x) - getset(repo, subset, y) 398 return getset(repo, subset, x) - getset(repo, subset, y)
399 399
400 def orset(repo, subset, *xs): 400 def _orsetlist(repo, subset, xs):
401 assert xs 401 assert xs
402 if len(xs) == 1: 402 if len(xs) == 1:
403 return getset(repo, subset, xs[0]) 403 return getset(repo, subset, xs[0])
404 p = len(xs) // 2 404 p = len(xs) // 2
405 a = orset(repo, subset, *xs[:p]) 405 a = _orsetlist(repo, subset, xs[:p])
406 b = orset(repo, subset, *xs[p:]) 406 b = _orsetlist(repo, subset, xs[p:])
407 return a + b 407 return a + b
408
409 def orset(repo, subset, x):
410 return _orsetlist(repo, subset, getlist(x))
408 411
409 def notset(repo, subset, x): 412 def notset(repo, subset, x):
410 return subset - getset(repo, subset, x) 413 return subset - getset(repo, subset, x)
411 414
412 def listset(repo, subset, *xs): 415 def listset(repo, subset, *xs):
2337 return _fixops(('dagrange', post, x[2][1])) 2340 return _fixops(('dagrange', post, x[2][1]))
2338 elif x[2][0] == 'rangepre': 2341 elif x[2][0] == 'rangepre':
2339 return _fixops(('range', post, x[2][1])) 2342 return _fixops(('range', post, x[2][1]))
2340 elif x[2][0] == 'rangeall': 2343 elif x[2][0] == 'rangeall':
2341 return _fixops(('rangepost', post)) 2344 return _fixops(('rangepost', post))
2345 elif op == 'or':
2346 # make number of arguments deterministic:
2347 # x + y + z -> (or x y z) -> (or (list x y z))
2348 return (op, _fixops(('list',) + x[1:]))
2342 2349
2343 return (op,) + tuple(_fixops(y) for y in x[1:]) 2350 return (op,) + tuple(_fixops(y) for y in x[1:])
2344 2351
2345 def _analyze(x): 2352 def _analyze(x):
2346 if x is None: 2353 if x is None:
2372 elif op == 'and': 2379 elif op == 'and':
2373 ta = _analyze(x[1]) 2380 ta = _analyze(x[1])
2374 tb = _analyze(x[2]) 2381 tb = _analyze(x[2])
2375 return (op, ta, tb) 2382 return (op, ta, tb)
2376 elif op == 'or': 2383 elif op == 'or':
2377 return (op,) + tuple(_analyze(y) for y in x[1:]) 2384 return (op, _analyze(x[1]))
2378 elif op == 'not': 2385 elif op == 'not':
2379 return (op, _analyze(x[1])) 2386 return (op, _analyze(x[1]))
2380 elif op == 'parentpost': 2387 elif op == 'parentpost':
2381 return (op, _analyze(x[1])) 2388 return (op, _analyze(x[1]))
2382 elif op == 'group': 2389 elif op == 'group':
2443 y = ('func', ('symbol', '_list'), ('string', s)) 2450 y = ('func', ('symbol', '_list'), ('string', s))
2444 w, t = _optimize(y, False) 2451 w, t = _optimize(y, False)
2445 ws.append(w) 2452 ws.append(w)
2446 ts.append(t) 2453 ts.append(t)
2447 del ss[:] 2454 del ss[:]
2448 for y in x[1:]: 2455 for y in getlist(x[1]):
2449 w, t = _optimize(y, False) 2456 w, t = _optimize(y, False)
2450 if t is not None and (t[0] == 'string' or t[0] == 'symbol'): 2457 if t is not None and (t[0] == 'string' or t[0] == 'symbol'):
2451 ss.append((w, t)) 2458 ss.append((w, t))
2452 continue 2459 continue
2453 flushss() 2460 flushss()
2457 if len(ts) == 1: 2464 if len(ts) == 1:
2458 return ws[0], ts[0] # 'or' operation is fully optimized out 2465 return ws[0], ts[0] # 'or' operation is fully optimized out
2459 # we can't reorder trees by weight because it would change the order. 2466 # we can't reorder trees by weight because it would change the order.
2460 # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a") 2467 # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a")
2461 # ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0])) 2468 # ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0]))
2462 return max(ws), (op,) + tuple(ts) 2469 return max(ws), (op, ('list',) + tuple(ts))
2463 elif op == 'not': 2470 elif op == 'not':
2464 # Optimize not public() to _notpublic() because we have a fast version 2471 # Optimize not public() to _notpublic() because we have a fast version
2465 if x[1] == ('func', ('symbol', 'public'), None): 2472 if x[1] == ('func', ('symbol', 'public'), None):
2466 newsym = ('func', ('symbol', '_notpublic'), None) 2473 newsym = ('func', ('symbol', '_notpublic'), None)
2467 o = _optimize(newsym, not small) 2474 o = _optimize(newsym, not small)
2611 if repo: 2618 if repo:
2612 lookup = repo.__contains__ 2619 lookup = repo.__contains__
2613 if len(specs) == 1: 2620 if len(specs) == 1:
2614 tree = parse(specs[0], lookup) 2621 tree = parse(specs[0], lookup)
2615 else: 2622 else:
2616 tree = ('or',) + tuple(parse(s, lookup) for s in specs) 2623 tree = ('or', ('list',) + tuple(parse(s, lookup) for s in specs))
2617 2624
2618 if ui: 2625 if ui:
2619 tree = expandaliases(ui, tree) 2626 tree = expandaliases(ui, tree)
2620 tree = foldconcat(tree) 2627 tree = foldconcat(tree)
2621 tree = analyze(tree) 2628 tree = analyze(tree)