author | Boris Feld <boris.feld@octobus.net> |
Tue, 11 Jul 2017 01:17:36 +0200 | |
changeset 33456 | ae052d04b89e |
parent 33416 | 9467d5337292 |
child 34010 | 72b5f4d53c58 |
permissions | -rw-r--r-- |
31024
0b8356705de6
revset: split language services to revsetlang module (API)
Yuya Nishihara <yuya@tcha.org>
parents:
31017
diff
changeset
|
1 |
# revsetlang.py - parser, tokenizer and utility for revision set language |
11275 | 2 |
# |
3 |
# Copyright 2010 Matt Mackall <mpm@selenic.com> |
|
4 |
# |
|
5 |
# This software may be used and distributed according to the terms of the |
|
6 |
# GNU General Public License version 2 or any later version. |
|
7 |
||
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
8 |
from __future__ import absolute_import |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
9 |
|
30071
2def3d55b1b9
revset: build _syminitletters from a saner source: the string module
Augie Fackler <augie@google.com>
parents:
30056
diff
changeset
|
10 |
import string |
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
11 |
|
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
12 |
from .i18n import _ |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
13 |
from . import ( |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
14 |
error, |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
15 |
node, |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
16 |
parser, |
30071
2def3d55b1b9
revset: build _syminitletters from a saner source: the string module
Augie Fackler <augie@google.com>
parents:
30056
diff
changeset
|
17 |
pycompat, |
31606
0b3eb280564b
revsetlang: perform quoting using ui.escapestr instead of repr()
Augie Fackler <augie@google.com>
parents:
31605
diff
changeset
|
18 |
util, |
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
19 |
) |
11275 | 20 |
|
21 |
elements = { |
|
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
22 |
# token-type: binding-strength, primary, prefix, infix, suffix |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
23 |
"(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None), |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
24 |
"[": (21, None, None, ("subscript", 1, "]"), None), |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
25 |
"#": (21, None, None, ("relation", 21), None), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
26 |
"##": (20, None, None, ("_concat", 20), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
27 |
"~": (18, None, None, ("ancestor", 18), None), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
28 |
"^": (18, None, None, ("parent", 18), "parentpost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
29 |
"-": (5, None, ("negate", 19), ("minus", 5), None), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
30 |
"::": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"), |
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
31 |
"..": (17, None, ("dagrangepre", 17), ("dagrange", 17), "dagrangepost"), |
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
32 |
":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
33 |
"not": (10, None, ("not", 10), None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
34 |
"!": (10, None, ("not", 10), None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
35 |
"and": (5, None, None, ("and", 5), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
36 |
"&": (5, None, None, ("and", 5), None), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
37 |
"%": (5, None, None, ("only", 5), "onlypost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
38 |
"or": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
39 |
"|": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
40 |
"+": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
41 |
"=": (3, None, None, ("keyvalue", 3), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
42 |
",": (2, None, None, ("list", 2), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
43 |
")": (0, None, None, None, None), |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
44 |
"]": (0, None, None, None, None), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
45 |
"symbol": (0, "symbol", None, None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
46 |
"string": (0, "string", None, None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
47 |
"end": (0, None, None, None, None), |
11275 | 48 |
} |
49 |
||
32291
bd872f64a8ba
cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents:
31997
diff
changeset
|
50 |
keywords = {'and', 'or', 'not'} |
11275 | 51 |
|
32291
bd872f64a8ba
cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents:
31997
diff
changeset
|
52 |
_quoteletters = {'"', "'"} |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
53 |
_simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%")) |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
54 |
|
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
55 |
# default set of valid characters for the initial letter of symbols |
31383
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
56 |
_syminitletters = set(pycompat.iterbytestr( |
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
57 |
string.ascii_letters.encode('ascii') + |
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
58 |
string.digits.encode('ascii') + |
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
59 |
'._@')) | set(map(pycompat.bytechr, xrange(128, 256))) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
60 |
|
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
61 |
# default set of valid characters for non-initial letters of symbols |
31383
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
62 |
_symletters = _syminitletters | set(pycompat.iterbytestr('-/')) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
63 |
|
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
64 |
def tokenize(program, lookup=None, syminitletters=None, symletters=None): |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
65 |
''' |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
66 |
Parse a revset statement into a stream of tokens |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
67 |
|
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
68 |
``syminitletters`` is the set of valid characters for the initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
69 |
letter of symbols. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
70 |
|
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
71 |
By default, character ``c`` is recognized as valid for initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
72 |
letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
73 |
|
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
74 |
``symletters`` is the set of valid characters for non-initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
75 |
letters of symbols. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
76 |
|
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
77 |
By default, character ``c`` is recognized as valid for non-initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
78 |
letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
79 |
|
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
80 |
Check that @ is a valid unquoted token character (issue3686): |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
81 |
>>> list(tokenize("@::")) |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
82 |
[('symbol', '@', 0), ('::', None, 1), ('end', None, 3)] |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
83 |
|
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
84 |
''' |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
85 |
program = pycompat.bytestr(program) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
86 |
if syminitletters is None: |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
87 |
syminitletters = _syminitletters |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
88 |
if symletters is None: |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
89 |
symletters = _symletters |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
90 |
|
25902
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
91 |
if program and lookup: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
92 |
# attempt to parse old-style ranges first to deal with |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
93 |
# things like old-tag which contain query metacharacters |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
94 |
parts = program.split(':', 1) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
95 |
if all(lookup(sym) for sym in parts if sym): |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
96 |
if parts[0]: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
97 |
yield ('symbol', parts[0], 0) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
98 |
if len(parts) > 1: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
99 |
s = len(parts[0]) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
100 |
yield (':', None, s) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
101 |
if parts[1]: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
102 |
yield ('symbol', parts[1], s + 1) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
103 |
yield ('end', None, len(program)) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
104 |
return |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
105 |
|
11275 | 106 |
pos, l = 0, len(program) |
107 |
while pos < l: |
|
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
108 |
c = program[pos] |
11275 | 109 |
if c.isspace(): # skip inter-token whitespace |
110 |
pass |
|
11278
7df88cdf47fd
revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents:
11275
diff
changeset
|
111 |
elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
112 |
yield ('::', None, pos) |
11278
7df88cdf47fd
revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents:
11275
diff
changeset
|
113 |
pos += 1 # skip ahead |
11275 | 114 |
elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
115 |
yield ('..', None, pos) |
11275 | 116 |
pos += 1 # skip ahead |
23742
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
117 |
elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
118 |
yield ('##', None, pos) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
119 |
pos += 1 # skip ahead |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
120 |
elif c in _simpleopletters: # handle simple operators |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
121 |
yield (c, None, pos) |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
122 |
elif (c in _quoteletters or c == 'r' and |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
123 |
program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
124 |
if c == 'r': |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
125 |
pos += 1 |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
126 |
c = program[pos] |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
127 |
decode = lambda x: x |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
128 |
else: |
26232
43f9976346e9
revset: handle error of string unescaping
Yuya Nishihara <yuya@tcha.org>
parents:
26212
diff
changeset
|
129 |
decode = parser.unescapestr |
11275 | 130 |
pos += 1 |
131 |
s = pos |
|
132 |
while pos < l: # find closing quote |
|
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
133 |
d = program[pos] |
11275 | 134 |
if d == '\\': # skip over escaped characters |
135 |
pos += 2 |
|
136 |
continue |
|
137 |
if d == c: |
|
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
138 |
yield ('string', decode(program[s:pos]), s) |
11275 | 139 |
break |
140 |
pos += 1 |
|
141 |
else: |
|
11383
de544774ebea
revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents:
11349
diff
changeset
|
142 |
raise error.ParseError(_("unterminated string"), s) |
16683 | 143 |
# gather up a symbol/keyword |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
144 |
elif c in syminitletters: |
11275 | 145 |
s = pos |
146 |
pos += 1 |
|
147 |
while pos < l: # find end of symbol |
|
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
148 |
d = program[pos] |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
149 |
if d not in symletters: |
11275 | 150 |
break |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
151 |
if d == '.' and program[pos - 1] == '.': # special case for .. |
11275 | 152 |
pos -= 1 |
153 |
break |
|
154 |
pos += 1 |
|
155 |
sym = program[s:pos] |
|
156 |
if sym in keywords: # operator keywords |
|
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
157 |
yield (sym, None, s) |
20780
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
158 |
elif '-' in sym: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
159 |
# some jerk gave us foo-bar-baz, try to check if it's a symbol |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
160 |
if lookup and lookup(sym): |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
161 |
# looks like a real symbol |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
162 |
yield ('symbol', sym, s) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
163 |
else: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
164 |
# looks like an expression |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
165 |
parts = sym.split('-') |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
166 |
for p in parts[:-1]: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
167 |
if p: # possible consecutive - |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
168 |
yield ('symbol', p, s) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
169 |
s += len(p) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
170 |
yield ('-', None, pos) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
171 |
s += 1 |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
172 |
if parts[-1]: # possible trailing - |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
173 |
yield ('symbol', parts[-1], s) |
11275 | 174 |
else: |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
175 |
yield ('symbol', sym, s) |
11275 | 176 |
pos -= 1 |
177 |
else: |
|
24708
fb47816e1a9c
revsets: more informative syntax error message
Ryan McElroy <rmcelroy@fb.com>
parents:
24518
diff
changeset
|
178 |
raise error.ParseError(_("syntax error in revset '%s'") % |
fb47816e1a9c
revsets: more informative syntax error message
Ryan McElroy <rmcelroy@fb.com>
parents:
24518
diff
changeset
|
179 |
program, pos) |
11275 | 180 |
pos += 1 |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
181 |
yield ('end', None, pos) |
11275 | 182 |
|
183 |
# helpers |
|
184 |
||
30802
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
185 |
_notset = object() |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
186 |
|
29441
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
187 |
def getsymbol(x): |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
188 |
if x and x[0] == 'symbol': |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
189 |
return x[1] |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
190 |
raise error.ParseError(_('not a symbol')) |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
191 |
|
11275 | 192 |
def getstring(x, err): |
11406
42408cd43f55
revset: fix up contains/getstring when no args passed
Matt Mackall <mpm@selenic.com>
parents:
11404
diff
changeset
|
193 |
if x and (x[0] == 'string' or x[0] == 'symbol'): |
11275 | 194 |
return x[1] |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
195 |
raise error.ParseError(err) |
11275 | 196 |
|
30802
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
197 |
def getinteger(x, err, default=_notset): |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
198 |
if not x and default is not _notset: |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
199 |
return default |
30801
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
200 |
try: |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
201 |
return int(getstring(x, err)) |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
202 |
except ValueError: |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
203 |
raise error.ParseError(err) |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
204 |
|
31997
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
205 |
def getboolean(x, err): |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
206 |
value = util.parsebool(getsymbol(x)) |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
207 |
if value is not None: |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
208 |
return value |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
209 |
raise error.ParseError(err) |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
210 |
|
11275 | 211 |
def getlist(x): |
212 |
if not x: |
|
213 |
return [] |
|
214 |
if x[0] == 'list': |
|
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
215 |
return list(x[1:]) |
11275 | 216 |
return [x] |
217 |
||
30804
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
218 |
def getrange(x, err): |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
219 |
if not x: |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
220 |
raise error.ParseError(err) |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
221 |
op = x[0] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
222 |
if op == 'range': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
223 |
return x[1], x[2] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
224 |
elif op == 'rangepre': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
225 |
return None, x[1] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
226 |
elif op == 'rangepost': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
227 |
return x[1], None |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
228 |
elif op == 'rangeall': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
229 |
return None, None |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
230 |
raise error.ParseError(err) |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
231 |
|
11339
744d5b73f776
revset: improve filter argument handling
Matt Mackall <mpm@selenic.com>
parents:
11304
diff
changeset
|
232 |
def getargs(x, min, max, err): |
11275 | 233 |
l = getlist(x) |
16161
5a627b49b4d9
graphlog: paths/-I/-X handling requires a new revset
Patrick Mezard <patrick@mezard.eu>
parents:
16096
diff
changeset
|
234 |
if len(l) < min or (max >= 0 and len(l) > max): |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
235 |
raise error.ParseError(err) |
11275 | 236 |
return l |
237 |
||
25767
026105c442d7
revset: rename getkwargs() to getargsdict()
Yuya Nishihara <yuya@tcha.org>
parents:
25766
diff
changeset
|
238 |
def getargsdict(x, funcname, keys): |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30719
diff
changeset
|
239 |
return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys), |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25704
diff
changeset
|
240 |
keyvaluenode='keyvalue', keynode='symbol') |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25704
diff
changeset
|
241 |
|
32912
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
242 |
def _isnamedfunc(x, funcname): |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
243 |
"""Check if given tree matches named function""" |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
244 |
return x and x[0] == 'func' and getsymbol(x[1]) == funcname |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
245 |
|
32913
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
246 |
def _isposargs(x, n): |
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
247 |
"""Check if given tree is n-length list of positional arguments""" |
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
248 |
l = getlist(x) |
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
249 |
return len(l) == n and all(y and y[0] != 'keyvalue' for y in l) |
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
250 |
|
32912
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
251 |
def _matchnamedfunc(x, funcname): |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
252 |
"""Return args tree if given tree matches named function; otherwise None |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
253 |
|
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
254 |
This can't be used for testing a nullary function since its args tree |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
255 |
is also None. Use _isnamedfunc() instead. |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
256 |
""" |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
257 |
if not _isnamedfunc(x, funcname): |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
258 |
return |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
259 |
return x[2] |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
260 |
|
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
261 |
# Constants for ordering requirement, used in _analyze(): |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
262 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
263 |
# If 'define', any nested functions and operations can change the ordering of |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
264 |
# the entries in the set. If 'follow', any nested functions and operations |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
265 |
# should take the ordering specified by the first operand to the '&' operator. |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
266 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
267 |
# For instance, |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
268 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
269 |
# X & (Y | Z) |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
270 |
# ^ ^^^^^^^ |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
271 |
# | follow |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
272 |
# define |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
273 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
274 |
# will be evaluated as 'or(y(x()), z(x()))', where 'x()' can change the order |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
275 |
# of the entries in the set, but 'y()', 'z()' and 'or()' shouldn't. |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
276 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
277 |
# 'any' means the order doesn't matter. For instance, |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
278 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
279 |
# X & !Y |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
280 |
# ^ |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
281 |
# any |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
282 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
283 |
# 'y()' can either enforce its ordering requirement or take the ordering |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
284 |
# specified by 'x()' because 'not()' doesn't care the order. |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
285 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
286 |
# Transition of ordering requirement: |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
287 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
288 |
# 1. starts with 'define' |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
289 |
# 2. shifts to 'follow' by 'x & y' |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
290 |
# 3. changes back to 'define' on function call 'f(x)' or function-like |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
291 |
# operation 'x (f) y' because 'f' may have its own ordering requirement |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
292 |
# for 'x' and 'y' (e.g. 'first(x)') |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
293 |
# |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
294 |
anyorder = 'any' # don't care the order |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
295 |
defineorder = 'define' # should define the order |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
296 |
followorder = 'follow' # must follow the current order |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
297 |
|
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
298 |
# transition table for 'x & y', from the current expression 'x' to 'y' |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
299 |
_tofolloworder = { |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
300 |
anyorder: anyorder, |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
301 |
defineorder: followorder, |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
302 |
followorder: followorder, |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
303 |
} |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
304 |
|
29117
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
305 |
def _matchonly(revs, bases): |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
306 |
""" |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
307 |
>>> f = lambda *args: _matchonly(*map(parse, args)) |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
308 |
>>> f('ancestors(A)', 'not ancestors(B)') |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
309 |
('list', ('symbol', 'A'), ('symbol', 'B')) |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
310 |
""" |
32912
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
311 |
ta = _matchnamedfunc(revs, 'ancestors') |
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
312 |
tb = bases and bases[0] == 'not' and _matchnamedfunc(bases[1], 'ancestors') |
32913
3292c0df64f7
revsetlang: check arguments passed to ancestors() before optimizing to only()
Yuya Nishihara <yuya@tcha.org>
parents:
32912
diff
changeset
|
313 |
if _isposargs(ta, 1) and _isposargs(tb, 1): |
32912
c808507cfbf0
revsetlang: factor out helper to match ancestors() in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
32291
diff
changeset
|
314 |
return ('list', ta, tb) |
29116
0c9b05dae010
revset: unnest isonly() closure from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29098
diff
changeset
|
315 |
|
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
316 |
def _fixops(x): |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
317 |
"""Rewrite raw parsed tree to resolve ambiguous syntax which cannot be |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
318 |
handled well by our simple top-down parser""" |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
319 |
if not isinstance(x, tuple): |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
320 |
return x |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
321 |
|
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
322 |
op = x[0] |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
323 |
if op == 'parent': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
324 |
# x^:y means (x^) : y, not x ^ (:y) |
29770
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
325 |
# x^: means (x^) :, not x ^ (:) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
326 |
post = ('parentpost', x[1]) |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
327 |
if x[2][0] == 'dagrangepre': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
328 |
return _fixops(('dagrange', post, x[2][1])) |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
329 |
elif x[2][0] == 'rangepre': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
330 |
return _fixops(('range', post, x[2][1])) |
29770
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
331 |
elif x[2][0] == 'rangeall': |
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
332 |
return _fixops(('rangepost', post)) |
29929
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
333 |
elif op == 'or': |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
334 |
# make number of arguments deterministic: |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
335 |
# x + y + z -> (or x y z) -> (or (list x y z)) |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
336 |
return (op, _fixops(('list',) + x[1:])) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
337 |
elif op == 'subscript' and x[1][0] == 'relation': |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
338 |
# x#y[z] ternary |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
339 |
return _fixops(('relsubscript', x[1][1], x[1][2], x[2])) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
340 |
|
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
341 |
return (op,) + tuple(_fixops(y) for y in x[1:]) |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
342 |
|
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
343 |
def _analyze(x, order): |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
344 |
if x is None: |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
345 |
return x |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
346 |
|
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
347 |
op = x[0] |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
348 |
if op == 'minus': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
349 |
return _analyze(('and', x[1], ('not', x[2])), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
350 |
elif op == 'only': |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
351 |
t = ('func', ('symbol', 'only'), ('list', x[1], x[2])) |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
352 |
return _analyze(t, order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
353 |
elif op == 'onlypost': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
354 |
return _analyze(('func', ('symbol', 'only'), x[1]), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
355 |
elif op == 'dagrangepre': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
356 |
return _analyze(('func', ('symbol', 'ancestors'), x[1]), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
357 |
elif op == 'dagrangepost': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
358 |
return _analyze(('func', ('symbol', 'descendants'), x[1]), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
359 |
elif op == 'negate': |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
360 |
s = getstring(x[1], _("can't negate that")) |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
361 |
return _analyze(('string', '-' + s), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
362 |
elif op in ('string', 'symbol'): |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
363 |
return x |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
364 |
elif op == 'and': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
365 |
ta = _analyze(x[1], order) |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
366 |
tb = _analyze(x[2], _tofolloworder[order]) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
367 |
return (op, ta, tb, order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
368 |
elif op == 'or': |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
369 |
return (op, _analyze(x[1], order), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
370 |
elif op == 'not': |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
371 |
return (op, _analyze(x[1], anyorder), order) |
30803
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
372 |
elif op == 'rangeall': |
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
373 |
return (op, None, order) |
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
374 |
elif op in ('rangepre', 'rangepost', 'parentpost'): |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
375 |
return (op, _analyze(x[1], defineorder), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
376 |
elif op == 'group': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
377 |
return _analyze(x[1], order) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
378 |
elif op in ('dagrange', 'range', 'parent', 'ancestor', 'relation', |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
379 |
'subscript'): |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
380 |
ta = _analyze(x[1], defineorder) |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
381 |
tb = _analyze(x[2], defineorder) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
382 |
return (op, ta, tb, order) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
383 |
elif op == 'relsubscript': |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
384 |
ta = _analyze(x[1], defineorder) |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
385 |
tb = _analyze(x[2], defineorder) |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
386 |
tc = _analyze(x[3], defineorder) |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
387 |
return (op, ta, tb, tc, order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
388 |
elif op == 'list': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
389 |
return (op,) + tuple(_analyze(y, order) for y in x[1:]) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
390 |
elif op == 'keyvalue': |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
391 |
return (op, x[1], _analyze(x[2], order)) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
392 |
elif op == 'func': |
29943
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
393 |
f = getsymbol(x[1]) |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
394 |
d = defineorder |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
395 |
if f == 'present': |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
396 |
# 'present(set)' is known to return the argument set with no |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
397 |
# modification, so forward the current order to its argument |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
398 |
d = order |
80c86b9bb40b
revset: forward ordering requirement to argument of present()
Yuya Nishihara <yuya@tcha.org>
parents:
29935
diff
changeset
|
399 |
return (op, x[1], _analyze(x[2], d), order) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
400 |
raise ValueError('invalid operator %r' % op) |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
401 |
|
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
402 |
def analyze(x, order=defineorder): |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
403 |
"""Transform raw parsed tree to evaluatable tree which can be fed to |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
404 |
optimize() or getset() |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
405 |
|
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
406 |
All pseudo operations should be mapped to real operations or functions |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
407 |
defined in methods or symbols table respectively. |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
408 |
|
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
409 |
'order' specifies how the current expression 'x' is ordered (see the |
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
410 |
constants defined above.) |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
411 |
""" |
29930
90455e7bf543
revset: infer ordering flag to teach if operation should define/follow order
Yuya Nishihara <yuya@tcha.org>
parents:
29929
diff
changeset
|
412 |
return _analyze(x, order) |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
413 |
|
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
414 |
def _optimize(x, small): |
13031
3da456d0c885
code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents:
12936
diff
changeset
|
415 |
if x is None: |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
416 |
return 0, x |
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
417 |
|
11275 | 418 |
smallbonus = 1 |
419 |
if small: |
|
420 |
smallbonus = .5 |
|
421 |
||
422 |
op = x[0] |
|
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
423 |
if op in ('string', 'symbol'): |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
424 |
return smallbonus, x # single revisions are small |
16859
eeb464ed7275
revset: drop unreachable code
Bryan O'Sullivan <bryano@fb.com>
parents:
16838
diff
changeset
|
425 |
elif op == 'and': |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
426 |
wa, ta = _optimize(x[1], True) |
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
427 |
wb, tb = _optimize(x[2], True) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
428 |
order = x[3] |
29116
0c9b05dae010
revset: unnest isonly() closure from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29098
diff
changeset
|
429 |
w = min(wa, wb) |
20499
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
430 |
|
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
431 |
# (::x and not ::y)/(not ::y and ::x) have a fast path |
29117
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
432 |
tm = _matchonly(ta, tb) or _matchonly(tb, ta) |
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
433 |
if tm: |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
434 |
return w, ('func', ('symbol', 'only'), tm, order) |
20499
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
435 |
|
28217
d2ac8b57a75d
revset: use smartset minus operator
Durham Goode <durham@fb.com>
parents:
28139
diff
changeset
|
436 |
if tb is not None and tb[0] == 'not': |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
437 |
return wa, ('difference', ta, tb[1], order) |
28217
d2ac8b57a75d
revset: use smartset minus operator
Durham Goode <durham@fb.com>
parents:
28139
diff
changeset
|
438 |
|
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
439 |
if wa > wb: |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
440 |
return w, (op, tb, ta, order) |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
441 |
return w, (op, ta, tb, order) |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
442 |
elif op == 'or': |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
443 |
# fast path for machine-generated expression, that is likely to have |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
444 |
# lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()' |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
445 |
order = x[2] |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
446 |
ws, ts, ss = [], [], [] |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
447 |
def flushss(): |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
448 |
if not ss: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
449 |
return |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
450 |
if len(ss) == 1: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
451 |
w, t = ss[0] |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
452 |
else: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
453 |
s = '\0'.join(t[1] for w, t in ss) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
454 |
y = ('func', ('symbol', '_list'), ('string', s), order) |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
455 |
w, t = _optimize(y, False) |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
456 |
ws.append(w) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
457 |
ts.append(t) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
458 |
del ss[:] |
29929
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
459 |
for y in getlist(x[1]): |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
460 |
w, t = _optimize(y, False) |
25996
b12e00a05d57
revset: prevent crash caused by empty group expression while optimizing "or"
Yuya Nishihara <yuya@tcha.org>
parents:
25995
diff
changeset
|
461 |
if t is not None and (t[0] == 'string' or t[0] == 'symbol'): |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
462 |
ss.append((w, t)) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
463 |
continue |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
464 |
flushss() |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
465 |
ws.append(w) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
466 |
ts.append(t) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
467 |
flushss() |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
468 |
if len(ts) == 1: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
469 |
return ws[0], ts[0] # 'or' operation is fully optimized out |
31800
c63cb2d10d6d
revsetlang: enable optimization of 'x + y' expression
Yuya Nishihara <yuya@tcha.org>
parents:
31636
diff
changeset
|
470 |
if order != defineorder: |
c63cb2d10d6d
revsetlang: enable optimization of 'x + y' expression
Yuya Nishihara <yuya@tcha.org>
parents:
31636
diff
changeset
|
471 |
# reorder by weight only when f(a + b) == f(b + a) |
c63cb2d10d6d
revsetlang: enable optimization of 'x + y' expression
Yuya Nishihara <yuya@tcha.org>
parents:
31636
diff
changeset
|
472 |
ts = [wt[1] for wt in sorted(zip(ws, ts), key=lambda wt: wt[0])] |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
473 |
return max(ws), (op, ('list',) + tuple(ts), order) |
11275 | 474 |
elif op == 'not': |
25191
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
475 |
# Optimize not public() to _notpublic() because we have a fast version |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
476 |
if x[1][:3] == ('func', ('symbol', 'public'), None): |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
477 |
order = x[1][3] |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
478 |
newsym = ('func', ('symbol', '_notpublic'), None, order) |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
479 |
o = _optimize(newsym, not small) |
25191
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
480 |
return o[0], o[1] |
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
481 |
else: |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
482 |
o = _optimize(x[1], not small) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
483 |
order = x[2] |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
484 |
return o[0], (op, o[1], order) |
30803
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
485 |
elif op == 'rangeall': |
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
486 |
return smallbonus, x |
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
487 |
elif op in ('rangepre', 'rangepost', 'parentpost'): |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
488 |
o = _optimize(x[1], small) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
489 |
order = x[2] |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
490 |
return o[0], (op, o[1], order) |
33415
371f59c6a89e
revset: do not compute weight for integer literal argument
Yuya Nishihara <yuya@tcha.org>
parents:
33336
diff
changeset
|
491 |
elif op in ('dagrange', 'range'): |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
492 |
wa, ta = _optimize(x[1], small) |
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
493 |
wb, tb = _optimize(x[2], small) |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
494 |
order = x[3] |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
495 |
return wa + wb, (op, ta, tb, order) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
496 |
elif op in ('parent', 'ancestor', 'relation', 'subscript'): |
33415
371f59c6a89e
revset: do not compute weight for integer literal argument
Yuya Nishihara <yuya@tcha.org>
parents:
33336
diff
changeset
|
497 |
w, t = _optimize(x[1], small) |
371f59c6a89e
revset: do not compute weight for integer literal argument
Yuya Nishihara <yuya@tcha.org>
parents:
33336
diff
changeset
|
498 |
order = x[3] |
371f59c6a89e
revset: do not compute weight for integer literal argument
Yuya Nishihara <yuya@tcha.org>
parents:
33336
diff
changeset
|
499 |
return w, (op, t, x[2], order) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
500 |
elif op == 'relsubscript': |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
501 |
w, t = _optimize(x[1], small) |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
502 |
order = x[4] |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
503 |
return w, (op, t, x[2], x[3], order) |
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
504 |
elif op == 'list': |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
505 |
ws, ts = zip(*(_optimize(y, small) for y in x[1:])) |
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
506 |
return sum(ws), (op,) + ts |
29766
5004ef47f437
revset: fix keyword arguments to go through optimization process
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
507 |
elif op == 'keyvalue': |
5004ef47f437
revset: fix keyword arguments to go through optimization process
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
508 |
w, t = _optimize(x[2], small) |
5004ef47f437
revset: fix keyword arguments to go through optimization process
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
509 |
return w, (op, x[1], t) |
11275 | 510 |
elif op == 'func': |
29441
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
511 |
f = getsymbol(x[1]) |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
512 |
wa, ta = _optimize(x[2], small) |
29898
7203400f91b0
revset: do not partial-match operator and function names in optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29897
diff
changeset
|
513 |
if f in ('author', 'branch', 'closed', 'date', 'desc', 'file', 'grep', |
30205
b4074417b661
revset: optimize for destination() being "inefficient"
Mads Kiilerich <madski@unity3d.com>
parents:
30179
diff
changeset
|
514 |
'keyword', 'outgoing', 'user', 'destination'): |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
515 |
w = 10 # slow |
29898
7203400f91b0
revset: do not partial-match operator and function names in optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29897
diff
changeset
|
516 |
elif f in ('modifies', 'adds', 'removes'): |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
517 |
w = 30 # slower |
11275 | 518 |
elif f == "contains": |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
519 |
w = 100 # very slow |
11275 | 520 |
elif f == "ancestor": |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
521 |
w = 1 * smallbonus |
30700
323f0c4b43f4
revset: categorize wdir() as very fast function
Yuya Nishihara <yuya@tcha.org>
parents:
30699
diff
changeset
|
522 |
elif f in ('reverse', 'limit', 'first', 'wdir', '_intlist'): |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
523 |
w = 0 |
29898
7203400f91b0
revset: do not partial-match operator and function names in optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29897
diff
changeset
|
524 |
elif f == "sort": |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
525 |
w = 10 # assume most sorts look at changelog |
11275 | 526 |
else: |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
527 |
w = 1 |
29932
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
528 |
order = x[3] |
09a84e747c88
revset: pass around ordering flags to operations
Yuya Nishihara <yuya@tcha.org>
parents:
29931
diff
changeset
|
529 |
return w + wa, (op, x[1], ta, order) |
29896
104914b03b83
revset: make optimize() reject unknown operators
Yuya Nishihara <yuya@tcha.org>
parents:
29814
diff
changeset
|
530 |
raise ValueError('invalid operator %r' % op) |
11275 | 531 |
|
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
532 |
def optimize(tree): |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
533 |
"""Optimize evaluatable tree |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
534 |
|
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
535 |
All pseudo operations should be transformed beforehand. |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
536 |
""" |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
537 |
_weight, newtree = _optimize(tree, small=True) |
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
538 |
return newtree |
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
539 |
|
23845
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
540 |
# the set of valid characters for the initial letter of symbols in |
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
541 |
# alias declarations and definitions |
30071
2def3d55b1b9
revset: build _syminitletters from a saner source: the string module
Augie Fackler <augie@google.com>
parents:
30056
diff
changeset
|
542 |
_aliassyminitletters = _syminitletters | set(pycompat.sysstr('$')) |
23845
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
543 |
|
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
544 |
def _parsewith(spec, lookup=None, syminitletters=None): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
545 |
"""Generate a parse tree of given spec with given tokenizing options |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
546 |
|
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
547 |
>>> _parsewith('foo($1)', syminitletters=_aliassyminitletters) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
548 |
('func', ('symbol', 'foo'), ('symbol', '$1')) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
549 |
>>> _parsewith('$1') |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
550 |
Traceback (most recent call last): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
551 |
... |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
552 |
ParseError: ("syntax error in revset '$1'", 0) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
553 |
>>> _parsewith('foo bar') |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
554 |
Traceback (most recent call last): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
555 |
... |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
556 |
ParseError: ('invalid token', 4) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
557 |
""" |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
558 |
p = parser.parser(elements) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
559 |
tree, pos = p.parse(tokenize(spec, lookup=lookup, |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
560 |
syminitletters=syminitletters)) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
561 |
if pos != len(spec): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
562 |
raise error.ParseError(_('invalid token'), pos) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
563 |
return _fixops(parser.simplifyinfixops(tree, ('list', 'or'))) |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
564 |
|
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
565 |
class _aliasrules(parser.basealiasrules): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
566 |
"""Parsing and expansion rule set of revset aliases""" |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
567 |
_section = _('revset alias') |
29074
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
568 |
|
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
569 |
@staticmethod |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
570 |
def _parse(spec): |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
571 |
"""Parse alias declaration/definition ``spec`` |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
572 |
|
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
573 |
This allows symbol names to use also ``$`` as an initial letter |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
574 |
(for backward compatibility), and callers of this function should |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
575 |
examine whether ``$`` is used also for unexpected symbols or not. |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
576 |
""" |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
577 |
return _parsewith(spec, syminitletters=_aliassyminitletters) |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
578 |
|
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
579 |
@staticmethod |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
580 |
def _trygetfunc(tree): |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
581 |
if tree[0] == 'func' and tree[1][0] == 'symbol': |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
582 |
return tree[1][1], getlist(tree[2]) |
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
583 |
|
33336
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
584 |
def expandaliases(tree, aliases, warn=None): |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
585 |
"""Expand aliases in a tree, aliases is a list of (name, value) tuples""" |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
586 |
aliases = _aliasrules.buildmap(aliases) |
28895
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28894
diff
changeset
|
587 |
tree = _aliasrules.expand(aliases, tree) |
29922
ae933e3e2226
revset: remove showwarning option from expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents:
29906
diff
changeset
|
588 |
# warn about problematic (but not referred) aliases |
33336
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
589 |
if warn is not None: |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
590 |
for name, alias in sorted(aliases.iteritems()): |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
591 |
if alias.error and not alias.warned: |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
592 |
warn(_('warning: %s\n') % (alias.error)) |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
593 |
alias.warned = True |
23725
6a81f88758aa
revset: delay showing parse error for the revset alias until it is referred
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23720
diff
changeset
|
594 |
return tree |
14098
9f5a0acb0056
revset aliases
Alexander Solovyov <alexander@solovyov.net>
parents:
14073
diff
changeset
|
595 |
|
23742
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
596 |
def foldconcat(tree): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
597 |
"""Fold elements to be concatenated by `##` |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
598 |
""" |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
599 |
if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
600 |
return tree |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
601 |
if tree[0] == '_concat': |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
602 |
pending = [tree] |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
603 |
l = [] |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
604 |
while pending: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
605 |
e = pending.pop() |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
606 |
if e[0] == '_concat': |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
607 |
pending.extend(reversed(e[1:])) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
608 |
elif e[0] in ('string', 'symbol'): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
609 |
l.append(e[1]) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
610 |
else: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
611 |
msg = _("\"##\" can't concatenate \"%s\" element") % (e[0]) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
612 |
raise error.ParseError(msg) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
613 |
return ('string', ''.join(l)) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
614 |
else: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
615 |
return tuple(foldconcat(t) for t in tree) |
14098
9f5a0acb0056
revset aliases
Alexander Solovyov <alexander@solovyov.net>
parents:
14073
diff
changeset
|
616 |
|
20779
ffc2295c6b80
revset: pass a lookup function to the tokenizer
Matt Mackall <mpm@selenic.com>
parents:
20754
diff
changeset
|
617 |
def parse(spec, lookup=None): |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
618 |
return _parsewith(spec, lookup=lookup) |
20779
ffc2295c6b80
revset: pass a lookup function to the tokenizer
Matt Mackall <mpm@selenic.com>
parents:
20754
diff
changeset
|
619 |
|
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
620 |
def _quote(s): |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
621 |
r"""Quote a value in order to make it safe for the revset engine. |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
622 |
|
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
623 |
>>> _quote('asdf') |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
624 |
"'asdf'" |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
625 |
>>> _quote("asdf'\"") |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
626 |
'\'asdf\\\'"\'' |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
627 |
>>> _quote('asdf\'') |
31606
0b3eb280564b
revsetlang: perform quoting using ui.escapestr instead of repr()
Augie Fackler <augie@google.com>
parents:
31605
diff
changeset
|
628 |
"'asdf\\''" |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
629 |
>>> _quote(1) |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
630 |
"'1'" |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
631 |
""" |
31636
f3b151278655
revsetlang: fix _quote on int on python3
Augie Fackler <raf@durin42.com>
parents:
31606
diff
changeset
|
632 |
return "'%s'" % util.escapestr(pycompat.bytestr(s)) |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
633 |
|
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
634 |
def formatspec(expr, *args): |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
635 |
''' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
636 |
This is a convenience function for using revsets internally, and |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
637 |
escapes arguments appropriately. Aliases are intentionally ignored |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
638 |
so that intended expression behavior isn't accidentally subverted. |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
639 |
|
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
640 |
Supported arguments: |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
641 |
|
15266
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
642 |
%r = revset expression, parenthesized |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
643 |
%d = int(arg), no quoting |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
644 |
%s = string(arg), escaped and single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
645 |
%b = arg.branch(), escaped and single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
646 |
%n = hex(arg), single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
647 |
%% = a literal '%' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
648 |
|
15266
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
649 |
Prefixing the type with 'l' specifies a parenthesized list of that type. |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
650 |
|
15268
bd5103819c2e
revset: fix %r handling in formatspec
Matt Mackall <mpm@selenic.com>
parents:
15266
diff
changeset
|
651 |
>>> formatspec('%r:: and %lr', '10 or 11', ("this()", "that()")) |
bd5103819c2e
revset: fix %r handling in formatspec
Matt Mackall <mpm@selenic.com>
parents:
15266
diff
changeset
|
652 |
'(10 or 11):: and ((this()) or (that()))' |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
653 |
>>> formatspec('%d:: and not %d::', 10, 20) |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
654 |
'10:: and not 20::' |
15325
cdf1daa3b83f
revset: deal with empty lists in formatspec
Matt Mackall <mpm@selenic.com>
parents:
15268
diff
changeset
|
655 |
>>> formatspec('%ld or %ld', [], [1]) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
656 |
"_list('') or 1" |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
657 |
>>> formatspec('keyword(%s)', 'foo\\xe9') |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
658 |
"keyword('foo\\\\xe9')" |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
659 |
>>> b = lambda: 'default' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
660 |
>>> b.branch = b |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
661 |
>>> formatspec('branch(%b)', b) |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
662 |
"branch('default')" |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
663 |
>>> formatspec('root(%ls)', ['a', 'b', 'c', 'd']) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
664 |
"root(_list('a\\x00b\\x00c\\x00d'))" |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
665 |
''' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
666 |
|
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
667 |
def argtype(c, arg): |
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
668 |
if c == 'd': |
31603
fbe8502c4480
revsetlang: portably bytestring-ify another pair of int() calls
Augie Fackler <augie@google.com>
parents:
31565
diff
changeset
|
669 |
return '%d' % int(arg) |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
670 |
elif c == 's': |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
671 |
return _quote(arg) |
15266
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
672 |
elif c == 'r': |
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
673 |
parse(arg) # make sure syntax errors are confined |
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
674 |
return '(%s)' % arg |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
675 |
elif c == 'n': |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
676 |
return _quote(node.hex(arg)) |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
677 |
elif c == 'b': |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
678 |
return _quote(arg.branch()) |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
679 |
|
15595
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
680 |
def listexp(s, t): |
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
681 |
l = len(s) |
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
682 |
if l == 0: |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
683 |
return "_list('')" |
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
684 |
elif l == 1: |
15595
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
685 |
return argtype(t, s[0]) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
686 |
elif t == 'd': |
31565
553ad16b274f
revsetlang: portably turn int into bytestring
Augie Fackler <augie@google.com>
parents:
31441
diff
changeset
|
687 |
return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
688 |
elif t == 's': |
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
689 |
return "_list('%s')" % "\0".join(s) |
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
690 |
elif t == 'n': |
20569
0d4be103c734
revset: added _hexlist method to replace _list for %ln
Lucas Moscovicz <lmoscovicz@fb.com>
parents:
20566
diff
changeset
|
691 |
return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
692 |
elif t == 'b': |
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
693 |
return "_list('%s')" % "\0".join(a.branch() for a in s) |
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
694 |
|
15791
a814f8fcc65a
Use explicit integer division
Martin Geisler <mg@aragost.com>
parents:
15726
diff
changeset
|
695 |
m = l // 2 |
15595
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
696 |
return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t)) |
a585d78e7b2f
revset: balance %l or-expressions (issue3129)
Matt Mackall <mpm@selenic.com>
parents:
15532
diff
changeset
|
697 |
|
31440
f784ba187089
py3: use bytestr wrapper in revsetlang.formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
31385
diff
changeset
|
698 |
expr = pycompat.bytestr(expr) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
699 |
ret = '' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
700 |
pos = 0 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
701 |
arg = 0 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
702 |
while pos < len(expr): |
31440
f784ba187089
py3: use bytestr wrapper in revsetlang.formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
31385
diff
changeset
|
703 |
c = expr[pos] |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
704 |
if c == '%': |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
705 |
pos += 1 |
31440
f784ba187089
py3: use bytestr wrapper in revsetlang.formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
31385
diff
changeset
|
706 |
d = expr[pos] |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
707 |
if d == '%': |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
708 |
ret += d |
15268
bd5103819c2e
revset: fix %r handling in formatspec
Matt Mackall <mpm@selenic.com>
parents:
15266
diff
changeset
|
709 |
elif d in 'dsnbr': |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
710 |
ret += argtype(d, args[arg]) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
711 |
arg += 1 |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
712 |
elif d == 'l': |
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
713 |
# a list of some type |
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
714 |
pos += 1 |
31440
f784ba187089
py3: use bytestr wrapper in revsetlang.formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
31385
diff
changeset
|
715 |
d = expr[pos] |
15596 | 716 |
ret += listexp(list(args[arg]), d) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
717 |
arg += 1 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
718 |
else: |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29365
diff
changeset
|
719 |
raise error.Abort(_('unexpected revspec format character %s') |
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29365
diff
changeset
|
720 |
% d) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
721 |
else: |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
722 |
ret += c |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
723 |
pos += 1 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
724 |
|
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
725 |
return ret |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
726 |
|
16218
81a1a00f5738
debugrevspec: pretty print output
Patrick Mezard <patrick@mezard.eu>
parents:
16185
diff
changeset
|
727 |
def prettyformat(tree): |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25251
diff
changeset
|
728 |
return parser.prettyformat(tree, ('string', 'symbol')) |
16218
81a1a00f5738
debugrevspec: pretty print output
Patrick Mezard <patrick@mezard.eu>
parents:
16185
diff
changeset
|
729 |
|
19719
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
730 |
def depth(tree): |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
731 |
if isinstance(tree, tuple): |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
732 |
return max(map(depth, tree)) + 1 |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
733 |
else: |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
734 |
return 0 |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
735 |
|
19720
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
736 |
def funcsused(tree): |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
737 |
if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'): |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
738 |
return set() |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
739 |
else: |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
740 |
funcs = set() |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
741 |
for s in tree[1:]: |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
742 |
funcs |= funcsused(s) |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
743 |
if tree[0] == 'func': |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
744 |
funcs.add(tree[1][1]) |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
745 |
return funcs |