##// END OF EJS Templates
revset: add experimental relation and subscript operators...
Yuya Nishihara -
r33416:9467d533 default
parent child Browse files
Show More
@@ -151,6 +151,15 b' def orset(repo, subset, x, order):'
151 151 def notset(repo, subset, x, order):
152 152 return subset - getset(repo, subset, x)
153 153
154 def relationset(repo, subset, x, y, order):
155 raise error.ParseError(_("can't use a relation in this context"))
156
157 def relsubscriptset(repo, subset, x, y, z, order):
158 raise error.ParseError(_("can't use a relation in this context"))
159
160 def subscriptset(repo, subset, x, y, order):
161 raise error.ParseError(_("can't use a subscript in this context"))
162
154 163 def listset(repo, subset, *xs):
155 164 raise error.ParseError(_("can't use a list in this context"),
156 165 hint=_('see hg help "revsets.x or y"'))
@@ -2004,6 +2013,9 b' methods = {'
2004 2013 "or": orset,
2005 2014 "not": notset,
2006 2015 "difference": differenceset,
2016 "relation": relationset,
2017 "relsubscript": relsubscriptset,
2018 "subscript": subscriptset,
2007 2019 "list": listset,
2008 2020 "keyvalue": keyvaluepair,
2009 2021 "func": func,
@@ -21,6 +21,8 b' from . import ('
21 21 elements = {
22 22 # token-type: binding-strength, primary, prefix, infix, suffix
23 23 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None),
24 "[": (21, None, None, ("subscript", 1, "]"), None),
25 "#": (21, None, None, ("relation", 21), None),
24 26 "##": (20, None, None, ("_concat", 20), None),
25 27 "~": (18, None, None, ("ancestor", 18), None),
26 28 "^": (18, None, None, ("parent", 18), "parentpost"),
@@ -39,6 +41,7 b' elements = {'
39 41 "=": (3, None, None, ("keyvalue", 3), None),
40 42 ",": (2, None, None, ("list", 2), None),
41 43 ")": (0, None, None, None, None),
44 "]": (0, None, None, None, None),
42 45 "symbol": (0, "symbol", None, None, None),
43 46 "string": (0, "string", None, None, None),
44 47 "end": (0, None, None, None, None),
@@ -47,7 +50,7 b' elements = {'
47 50 keywords = {'and', 'or', 'not'}
48 51
49 52 _quoteletters = {'"', "'"}
50 _simpleopletters = set(pycompat.iterbytestr("():=,-|&+!~^%"))
53 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%"))
51 54
52 55 # default set of valid characters for the initial letter of symbols
53 56 _syminitletters = set(pycompat.iterbytestr(
@@ -331,6 +334,9 b' def _fixops(x):'
331 334 # make number of arguments deterministic:
332 335 # x + y + z -> (or x y z) -> (or (list x y z))
333 336 return (op, _fixops(('list',) + x[1:]))
337 elif op == 'subscript' and x[1][0] == 'relation':
338 # x#y[z] ternary
339 return _fixops(('relsubscript', x[1][1], x[1][2], x[2]))
334 340
335 341 return (op,) + tuple(_fixops(y) for y in x[1:])
336 342
@@ -369,10 +375,16 b' def _analyze(x, order):'
369 375 return (op, _analyze(x[1], defineorder), order)
370 376 elif op == 'group':
371 377 return _analyze(x[1], order)
372 elif op in ('dagrange', 'range', 'parent', 'ancestor'):
378 elif op in ('dagrange', 'range', 'parent', 'ancestor', 'relation',
379 'subscript'):
373 380 ta = _analyze(x[1], defineorder)
374 381 tb = _analyze(x[2], defineorder)
375 382 return (op, ta, tb, order)
383 elif op == 'relsubscript':
384 ta = _analyze(x[1], defineorder)
385 tb = _analyze(x[2], defineorder)
386 tc = _analyze(x[3], defineorder)
387 return (op, ta, tb, tc, order)
376 388 elif op == 'list':
377 389 return (op,) + tuple(_analyze(y, order) for y in x[1:])
378 390 elif op == 'keyvalue':
@@ -481,10 +493,14 b' def _optimize(x, small):'
481 493 wb, tb = _optimize(x[2], small)
482 494 order = x[3]
483 495 return wa + wb, (op, ta, tb, order)
484 elif op in ('parent', 'ancestor'):
496 elif op in ('parent', 'ancestor', 'relation', 'subscript'):
485 497 w, t = _optimize(x[1], small)
486 498 order = x[3]
487 499 return w, (op, t, x[2], order)
500 elif op == 'relsubscript':
501 w, t = _optimize(x[1], small)
502 order = x[4]
503 return w, (op, t, x[2], x[3], order)
488 504 elif op == 'list':
489 505 ws, ts = zip(*(_optimize(y, small) for y in x[1:]))
490 506 return sum(ws), (op,) + ts
@@ -812,7 +812,7 b' check error cases'
812 812 abort: line range exceeds file size
813 813 [255]
814 814 $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])'
815 hg: parse error at 43: syntax error in revset 'followlines(baz, 2:4, startrev=20, descend=[1])'
815 hg: parse error at 43: not a prefix: [
816 816 [255]
817 817 $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)'
818 818 hg: parse error: descend argument must be a boolean
@@ -500,6 +500,151 b' keyword arguments'
500 500 hg: parse error: can't use a key-value pair in this context
501 501 [255]
502 502
503 relation-subscript operator has the highest binding strength (as function call):
504
505 $ hg debugrevspec -p parsed 'tip:tip^#generations[-1]'
506 * parsed:
507 (range
508 ('symbol', 'tip')
509 (relsubscript
510 (parentpost
511 ('symbol', 'tip'))
512 ('symbol', 'generations')
513 (negate
514 ('symbol', '1'))))
515 hg: parse error: can't use a relation in this context
516 [255]
517
518 $ hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'
519 * parsed:
520 (not
521 (relsubscript
522 (func
523 ('symbol', 'public')
524 None)
525 ('symbol', 'generations')
526 ('symbol', '0')))
527 hg: parse error: can't use a relation in this context
528 [255]
529
530 left-hand side of relation-subscript operator should be optimized recursively:
531
532 $ hg debugrevspec -p analyzed -p optimized --no-show-revs \
533 > '(not public())#generations[0]'
534 * analyzed:
535 (relsubscript
536 (not
537 (func
538 ('symbol', 'public')
539 None
540 any)
541 define)
542 ('symbol', 'generations')
543 ('symbol', '0')
544 define)
545 * optimized:
546 (relsubscript
547 (func
548 ('symbol', '_notpublic')
549 None
550 any)
551 ('symbol', 'generations')
552 ('symbol', '0')
553 define)
554 hg: parse error: can't use a relation in this context
555 [255]
556
557 resolution of subscript and relation-subscript ternary operators:
558
559 $ hg debugrevspec -p analyzed 'tip[0]'
560 * analyzed:
561 (subscript
562 ('symbol', 'tip')
563 ('symbol', '0')
564 define)
565 hg: parse error: can't use a subscript in this context
566 [255]
567
568 $ hg debugrevspec -p analyzed 'tip#rel[0]'
569 * analyzed:
570 (relsubscript
571 ('symbol', 'tip')
572 ('symbol', 'rel')
573 ('symbol', '0')
574 define)
575 hg: parse error: can't use a relation in this context
576 [255]
577
578 $ hg debugrevspec -p analyzed '(tip#rel)[0]'
579 * analyzed:
580 (subscript
581 (relation
582 ('symbol', 'tip')
583 ('symbol', 'rel')
584 define)
585 ('symbol', '0')
586 define)
587 hg: parse error: can't use a subscript in this context
588 [255]
589
590 $ hg debugrevspec -p analyzed 'tip#rel[0][1]'
591 * analyzed:
592 (subscript
593 (relsubscript
594 ('symbol', 'tip')
595 ('symbol', 'rel')
596 ('symbol', '0')
597 define)
598 ('symbol', '1')
599 define)
600 hg: parse error: can't use a subscript in this context
601 [255]
602
603 $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'
604 * analyzed:
605 (relsubscript
606 (relation
607 ('symbol', 'tip')
608 ('symbol', 'rel0')
609 define)
610 ('symbol', 'rel1')
611 ('symbol', '1')
612 define)
613 hg: parse error: can't use a relation in this context
614 [255]
615
616 $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'
617 * analyzed:
618 (relsubscript
619 (relsubscript
620 ('symbol', 'tip')
621 ('symbol', 'rel0')
622 ('symbol', '0')
623 define)
624 ('symbol', 'rel1')
625 ('symbol', '1')
626 define)
627 hg: parse error: can't use a relation in this context
628 [255]
629
630 parse errors of relation, subscript and relation-subscript operators:
631
632 $ hg debugrevspec '[0]'
633 hg: parse error at 0: not a prefix: [
634 [255]
635 $ hg debugrevspec '.#'
636 hg: parse error at 2: not a prefix: end
637 [255]
638 $ hg debugrevspec '#rel'
639 hg: parse error at 0: not a prefix: #
640 [255]
641 $ hg debugrevspec '.#rel[0'
642 hg: parse error at 7: unexpected token: end
643 [255]
644 $ hg debugrevspec '.]'
645 hg: parse error at 1: invalid token
646 [255]
647
503 648 parsed tree at stages:
504 649
505 650 $ hg debugrevspec -p all '()'
General Comments 0
You need to be logged in to leave comments. Login now