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': |