351 All pseudo operations should be mapped to real operations or functions |
351 All pseudo operations should be mapped to real operations or functions |
352 defined in methods or symbols table respectively. |
352 defined in methods or symbols table respectively. |
353 """ |
353 """ |
354 return _analyze(x) |
354 return _analyze(x) |
355 |
355 |
356 def _optimize(x, small): |
356 def _optimize(x): |
357 if x is None: |
357 if x is None: |
358 return 0, x |
358 return 0, x |
359 |
359 |
360 smallbonus = 1 |
|
361 if small: |
|
362 smallbonus = .5 |
|
363 |
|
364 op = x[0] |
360 op = x[0] |
365 if op in ('string', 'symbol'): |
361 if op in ('string', 'symbol'): |
366 return smallbonus, x # single revisions are small |
362 return 0.5, x # single revisions are small |
367 elif op == 'and': |
363 elif op == 'and': |
368 wa, ta = _optimize(x[1], True) |
364 wa, ta = _optimize(x[1]) |
369 wb, tb = _optimize(x[2], True) |
365 wb, tb = _optimize(x[2]) |
370 w = min(wa, wb) |
366 w = min(wa, wb) |
371 |
367 |
372 # (draft/secret/_notpublic() & ::x) have a fast path |
368 # (draft/secret/_notpublic() & ::x) have a fast path |
373 m = _match('_() & ancestors(_)', ('and', ta, tb)) |
369 m = _match('_() & ancestors(_)', ('and', ta, tb)) |
374 if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}: |
370 if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}: |
414 return ws[0], ts[0] # 'or' operation is fully optimized out |
410 return ws[0], ts[0] # 'or' operation is fully optimized out |
415 return max(ws), (op, ('list',) + tuple(ts)) |
411 return max(ws), (op, ('list',) + tuple(ts)) |
416 elif op == 'not': |
412 elif op == 'not': |
417 # Optimize not public() to _notpublic() because we have a fast version |
413 # Optimize not public() to _notpublic() because we have a fast version |
418 if _match('public()', x[1]): |
414 if _match('public()', x[1]): |
419 o = _optimize(_build('_notpublic()'), not small) |
415 o = _optimize(_build('_notpublic()')) |
420 return o[0], o[1] |
416 return o[0], o[1] |
421 else: |
417 else: |
422 o = _optimize(x[1], not small) |
418 o = _optimize(x[1]) |
423 return o[0], (op, o[1]) |
419 return o[0], (op, o[1]) |
424 elif op == 'rangeall': |
420 elif op == 'rangeall': |
425 return smallbonus, x |
421 return 1, x |
426 elif op in ('rangepre', 'rangepost', 'parentpost'): |
422 elif op in ('rangepre', 'rangepost', 'parentpost'): |
427 o = _optimize(x[1], small) |
423 o = _optimize(x[1]) |
428 return o[0], (op, o[1]) |
424 return o[0], (op, o[1]) |
429 elif op in ('dagrange', 'range'): |
425 elif op in ('dagrange', 'range'): |
430 wa, ta = _optimize(x[1], small) |
426 wa, ta = _optimize(x[1]) |
431 wb, tb = _optimize(x[2], small) |
427 wb, tb = _optimize(x[2]) |
432 return wa + wb, (op, ta, tb) |
428 return wa + wb, (op, ta, tb) |
433 elif op in ('parent', 'ancestor', 'relation', 'subscript'): |
429 elif op in ('parent', 'ancestor', 'relation', 'subscript'): |
434 w, t = _optimize(x[1], small) |
430 w, t = _optimize(x[1]) |
435 return w, (op, t, x[2]) |
431 return w, (op, t, x[2]) |
436 elif op == 'relsubscript': |
432 elif op == 'relsubscript': |
437 w, t = _optimize(x[1], small) |
433 w, t = _optimize(x[1]) |
438 return w, (op, t, x[2], x[3]) |
434 return w, (op, t, x[2], x[3]) |
439 elif op == 'list': |
435 elif op == 'list': |
440 ws, ts = zip(*(_optimize(y, small) for y in x[1:])) |
436 ws, ts = zip(*(_optimize(y) for y in x[1:])) |
441 return sum(ws), (op,) + ts |
437 return sum(ws), (op,) + ts |
442 elif op == 'keyvalue': |
438 elif op == 'keyvalue': |
443 w, t = _optimize(x[2], small) |
439 w, t = _optimize(x[2]) |
444 return w, (op, x[1], t) |
440 return w, (op, x[1], t) |
445 elif op == 'func': |
441 elif op == 'func': |
446 f = getsymbol(x[1]) |
442 f = getsymbol(x[1]) |
447 wa, ta = _optimize(x[2], small) |
443 wa, ta = _optimize(x[2]) |
448 if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep', |
444 if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep', |
449 'keyword', 'outgoing', 'user', 'destination'): |
445 'keyword', 'outgoing', 'user', 'destination'): |
450 w = 10 # slow |
446 w = 10 # slow |
451 elif f in ('modifies', 'adds', 'removes'): |
447 elif f in ('modifies', 'adds', 'removes'): |
452 w = 30 # slower |
448 w = 30 # slower |
453 elif f == "contains": |
449 elif f == "contains": |
454 w = 100 # very slow |
450 w = 100 # very slow |
455 elif f == "ancestor": |
451 elif f == "ancestor": |
456 w = 1 * smallbonus |
452 w = 0.5 |
457 elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'): |
453 elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'): |
458 w = 0 |
454 w = 0 |
459 elif f == "sort": |
455 elif f == "sort": |
460 w = 10 # assume most sorts look at changelog |
456 w = 10 # assume most sorts look at changelog |
461 else: |
457 else: |