##// END OF EJS Templates
revset: infer ordering flag to teach if operation should define/follow order...
Yuya Nishihara -
r29930:90455e7b default
parent child Browse files
Show More
@@ -2310,6 +2310,50 methods = {
2310 2310 "parentpost": p1,
2311 2311 }
2312 2312
2313 # Constants for ordering requirement, used in _analyze():
2314 #
2315 # If 'define', any nested functions and operations can change the ordering of
2316 # the entries in the set. If 'follow', any nested functions and operations
2317 # should take the ordering specified by the first operand to the '&' operator.
2318 #
2319 # For instance,
2320 #
2321 # X & (Y | Z)
2322 # ^ ^^^^^^^
2323 # | follow
2324 # define
2325 #
2326 # will be evaluated as 'or(y(x()), z(x()))', where 'x()' can change the order
2327 # of the entries in the set, but 'y()', 'z()' and 'or()' shouldn't.
2328 #
2329 # 'any' means the order doesn't matter. For instance,
2330 #
2331 # X & !Y
2332 # ^
2333 # any
2334 #
2335 # 'y()' can either enforce its ordering requirement or take the ordering
2336 # specified by 'x()' because 'not()' doesn't care the order.
2337 #
2338 # Transition of ordering requirement:
2339 #
2340 # 1. starts with 'define'
2341 # 2. shifts to 'follow' by 'x & y'
2342 # 3. changes back to 'define' on function call 'f(x)' or function-like
2343 # operation 'x (f) y' because 'f' may have its own ordering requirement
2344 # for 'x' and 'y' (e.g. 'first(x)')
2345 #
2346 anyorder = 'any' # don't care the order
2347 defineorder = 'define' # should define the order
2348 followorder = 'follow' # must follow the current order
2349
2350 # transition table for 'x & y', from the current expression 'x' to 'y'
2351 _tofolloworder = {
2352 anyorder: anyorder,
2353 defineorder: followorder,
2354 followorder: followorder,
2355 }
2356
2313 2357 def _matchonly(revs, bases):
2314 2358 """
2315 2359 >>> f = lambda *args: _matchonly(*map(parse, args))
@@ -2349,65 +2393,68 def _fixops(x):
2349 2393
2350 2394 return (op,) + tuple(_fixops(y) for y in x[1:])
2351 2395
2352 def _analyze(x):
2396 def _analyze(x, order):
2353 2397 if x is None:
2354 2398 return x
2355 2399
2356 2400 op = x[0]
2357 2401 if op == 'minus':
2358 return _analyze(('and', x[1], ('not', x[2])))
2402 return _analyze(('and', x[1], ('not', x[2])), order)
2359 2403 elif op == 'only':
2360 2404 t = ('func', ('symbol', 'only'), ('list', x[1], x[2]))
2361 return _analyze(t)
2405 return _analyze(t, order)
2362 2406 elif op == 'onlypost':
2363 return _analyze(('func', ('symbol', 'only'), x[1]))
2407 return _analyze(('func', ('symbol', 'only'), x[1]), order)
2364 2408 elif op == 'dagrangepre':
2365 return _analyze(('func', ('symbol', 'ancestors'), x[1]))
2409 return _analyze(('func', ('symbol', 'ancestors'), x[1]), order)
2366 2410 elif op == 'dagrangepost':
2367 return _analyze(('func', ('symbol', 'descendants'), x[1]))
2411 return _analyze(('func', ('symbol', 'descendants'), x[1]), order)
2368 2412 elif op == 'rangeall':
2369 return _analyze(('range', ('string', '0'), ('string', 'tip')))
2413 return _analyze(('range', ('string', '0'), ('string', 'tip')), order)
2370 2414 elif op == 'rangepre':
2371 return _analyze(('range', ('string', '0'), x[1]))
2415 return _analyze(('range', ('string', '0'), x[1]), order)
2372 2416 elif op == 'rangepost':
2373 return _analyze(('range', x[1], ('string', 'tip')))
2417 return _analyze(('range', x[1], ('string', 'tip')), order)
2374 2418 elif op == 'negate':
2375 2419 s = getstring(x[1], _("can't negate that"))
2376 return _analyze(('string', '-' + s))
2420 return _analyze(('string', '-' + s), order)
2377 2421 elif op in ('string', 'symbol'):
2378 2422 return x
2379 2423 elif op == 'and':
2380 ta = _analyze(x[1])
2381 tb = _analyze(x[2])
2424 ta = _analyze(x[1], order)
2425 tb = _analyze(x[2], _tofolloworder[order])
2382 2426 return (op, ta, tb)
2383 2427 elif op == 'or':
2384 return (op, _analyze(x[1]))
2428 return (op, _analyze(x[1], order))
2385 2429 elif op == 'not':
2386 return (op, _analyze(x[1]))
2430 return (op, _analyze(x[1], anyorder))
2387 2431 elif op == 'parentpost':
2388 return (op, _analyze(x[1]))
2432 return (op, _analyze(x[1], defineorder))
2389 2433 elif op == 'group':
2390 return _analyze(x[1])
2434 return _analyze(x[1], order)
2391 2435 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
2392 ta = _analyze(x[1])
2393 tb = _analyze(x[2])
2436 ta = _analyze(x[1], defineorder)
2437 tb = _analyze(x[2], defineorder)
2394 2438 return (op, ta, tb)
2395 2439 elif op == 'list':
2396 return (op,) + tuple(_analyze(y) for y in x[1:])
2440 return (op,) + tuple(_analyze(y, order) for y in x[1:])
2397 2441 elif op == 'keyvalue':
2398 return (op, x[1], _analyze(x[2]))
2442 return (op, x[1], _analyze(x[2], order))
2399 2443 elif op == 'func':
2400 return (op, x[1], _analyze(x[2]))
2444 return (op, x[1], _analyze(x[2], defineorder))
2401 2445 raise ValueError('invalid operator %r' % op)
2402 2446
2403 def analyze(x):
2447 def analyze(x, order=defineorder):
2404 2448 """Transform raw parsed tree to evaluatable tree which can be fed to
2405 2449 optimize() or getset()
2406 2450
2407 2451 All pseudo operations should be mapped to real operations or functions
2408 2452 defined in methods or symbols table respectively.
2453
2454 'order' specifies how the current expression 'x' is ordered (see the
2455 constants defined above.)
2409 2456 """
2410 return _analyze(x)
2457 return _analyze(x, order)
2411 2458
2412 2459 def _optimize(x, small):
2413 2460 if x is None:
General Comments 0
You need to be logged in to leave comments. Login now