Show More
@@ -2310,6 +2310,50 methods = { | |||||
2310 | "parentpost": p1, |
|
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 | def _matchonly(revs, bases): |
|
2357 | def _matchonly(revs, bases): | |
2314 | """ |
|
2358 | """ | |
2315 | >>> f = lambda *args: _matchonly(*map(parse, args)) |
|
2359 | >>> f = lambda *args: _matchonly(*map(parse, args)) | |
@@ -2349,65 +2393,68 def _fixops(x): | |||||
2349 |
|
2393 | |||
2350 | return (op,) + tuple(_fixops(y) for y in x[1:]) |
|
2394 | return (op,) + tuple(_fixops(y) for y in x[1:]) | |
2351 |
|
2395 | |||
2352 | def _analyze(x): |
|
2396 | def _analyze(x, order): | |
2353 | if x is None: |
|
2397 | if x is None: | |
2354 | return x |
|
2398 | return x | |
2355 |
|
2399 | |||
2356 | op = x[0] |
|
2400 | op = x[0] | |
2357 | if op == 'minus': |
|
2401 | if op == 'minus': | |
2358 | return _analyze(('and', x[1], ('not', x[2]))) |
|
2402 | return _analyze(('and', x[1], ('not', x[2])), order) | |
2359 | elif op == 'only': |
|
2403 | elif op == 'only': | |
2360 | t = ('func', ('symbol', 'only'), ('list', x[1], x[2])) |
|
2404 | t = ('func', ('symbol', 'only'), ('list', x[1], x[2])) | |
2361 | return _analyze(t) |
|
2405 | return _analyze(t, order) | |
2362 | elif op == 'onlypost': |
|
2406 | elif op == 'onlypost': | |
2363 | return _analyze(('func', ('symbol', 'only'), x[1])) |
|
2407 | return _analyze(('func', ('symbol', 'only'), x[1]), order) | |
2364 | elif op == 'dagrangepre': |
|
2408 | elif op == 'dagrangepre': | |
2365 | return _analyze(('func', ('symbol', 'ancestors'), x[1])) |
|
2409 | return _analyze(('func', ('symbol', 'ancestors'), x[1]), order) | |
2366 | elif op == 'dagrangepost': |
|
2410 | elif op == 'dagrangepost': | |
2367 | return _analyze(('func', ('symbol', 'descendants'), x[1])) |
|
2411 | return _analyze(('func', ('symbol', 'descendants'), x[1]), order) | |
2368 | elif op == 'rangeall': |
|
2412 | elif op == 'rangeall': | |
2369 | return _analyze(('range', ('string', '0'), ('string', 'tip'))) |
|
2413 | return _analyze(('range', ('string', '0'), ('string', 'tip')), order) | |
2370 | elif op == 'rangepre': |
|
2414 | elif op == 'rangepre': | |
2371 | return _analyze(('range', ('string', '0'), x[1])) |
|
2415 | return _analyze(('range', ('string', '0'), x[1]), order) | |
2372 | elif op == 'rangepost': |
|
2416 | elif op == 'rangepost': | |
2373 | return _analyze(('range', x[1], ('string', 'tip'))) |
|
2417 | return _analyze(('range', x[1], ('string', 'tip')), order) | |
2374 | elif op == 'negate': |
|
2418 | elif op == 'negate': | |
2375 | s = getstring(x[1], _("can't negate that")) |
|
2419 | s = getstring(x[1], _("can't negate that")) | |
2376 | return _analyze(('string', '-' + s)) |
|
2420 | return _analyze(('string', '-' + s), order) | |
2377 | elif op in ('string', 'symbol'): |
|
2421 | elif op in ('string', 'symbol'): | |
2378 | return x |
|
2422 | return x | |
2379 | elif op == 'and': |
|
2423 | elif op == 'and': | |
2380 | ta = _analyze(x[1]) |
|
2424 | ta = _analyze(x[1], order) | |
2381 | tb = _analyze(x[2]) |
|
2425 | tb = _analyze(x[2], _tofolloworder[order]) | |
2382 | return (op, ta, tb) |
|
2426 | return (op, ta, tb) | |
2383 | elif op == 'or': |
|
2427 | elif op == 'or': | |
2384 | return (op, _analyze(x[1])) |
|
2428 | return (op, _analyze(x[1], order)) | |
2385 | elif op == 'not': |
|
2429 | elif op == 'not': | |
2386 | return (op, _analyze(x[1])) |
|
2430 | return (op, _analyze(x[1], anyorder)) | |
2387 | elif op == 'parentpost': |
|
2431 | elif op == 'parentpost': | |
2388 | return (op, _analyze(x[1])) |
|
2432 | return (op, _analyze(x[1], defineorder)) | |
2389 | elif op == 'group': |
|
2433 | elif op == 'group': | |
2390 | return _analyze(x[1]) |
|
2434 | return _analyze(x[1], order) | |
2391 | elif op in ('dagrange', 'range', 'parent', 'ancestor'): |
|
2435 | elif op in ('dagrange', 'range', 'parent', 'ancestor'): | |
2392 | ta = _analyze(x[1]) |
|
2436 | ta = _analyze(x[1], defineorder) | |
2393 | tb = _analyze(x[2]) |
|
2437 | tb = _analyze(x[2], defineorder) | |
2394 | return (op, ta, tb) |
|
2438 | return (op, ta, tb) | |
2395 | elif op == 'list': |
|
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 | elif op == 'keyvalue': |
|
2441 | elif op == 'keyvalue': | |
2398 | return (op, x[1], _analyze(x[2])) |
|
2442 | return (op, x[1], _analyze(x[2], order)) | |
2399 | elif op == 'func': |
|
2443 | elif op == 'func': | |
2400 | return (op, x[1], _analyze(x[2])) |
|
2444 | return (op, x[1], _analyze(x[2], defineorder)) | |
2401 | raise ValueError('invalid operator %r' % op) |
|
2445 | raise ValueError('invalid operator %r' % op) | |
2402 |
|
2446 | |||
2403 | def analyze(x): |
|
2447 | def analyze(x, order=defineorder): | |
2404 | """Transform raw parsed tree to evaluatable tree which can be fed to |
|
2448 | """Transform raw parsed tree to evaluatable tree which can be fed to | |
2405 | optimize() or getset() |
|
2449 | optimize() or getset() | |
2406 |
|
2450 | |||
2407 | All pseudo operations should be mapped to real operations or functions |
|
2451 | All pseudo operations should be mapped to real operations or functions | |
2408 | defined in methods or symbols table respectively. |
|
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 | def _optimize(x, small): |
|
2459 | def _optimize(x, small): | |
2413 | if x is None: |
|
2460 | if x is None: |
General Comments 0
You need to be logged in to leave comments.
Login now