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