Skip to content

Commit 0786ef1

Browse files
committed
Add compatibility code to not break access of existing int attributes
E.g. 0x1.bit_length() will not require parentheses around the hexadecimal integer literal (like 1.bit_length() for decimal int).
1 parent 8ce8ea4 commit 0786ef1

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

Lib/test/test_grammar.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ def test_plain_integers(self):
178178
else:
179179
self.fail('Weird maxsize value %r' % maxsize)
180180

181+
def test_attrs_on_hexintegers(self):
182+
good_meth = [m for m in dir(int) if not m.startswith('_')]
183+
for m in good_meth:
184+
self.assertEqual(eval('0x1.' + m), eval('(0x1).' + m))
185+
self.check_syntax_error('0x1.spam', "invalid hexadecimal literal",
186+
lineno=1, offset=4)
187+
self.check_syntax_error('0x1.foo', "invalid hexadecimal literal",
188+
lineno=1, offset=5)
189+
181190
def test_long_integers(self):
182191
x = 0
183192
x = 0xffffffffffffffff

Parser/lexer/lexer.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,24 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
779779
if (c == '.') {
780780
c = tok_nextc(tok);
781781
hexfraction:
782+
/* Allow attribute access on hexadecimal integer literals for
783+
* for existing public attributes on int's, e.g. 0x1.bit_length(). */
784+
if ((c == 'a' && lookahead(tok, "s_integer_ratio")) ||
785+
(c == 't' && lookahead(tok, "o_bytes")) ||
786+
(c == 'b' && (lookahead(tok, "it_count") ||
787+
lookahead(tok, "it_length"))) ||
788+
(c == 'c' && lookahead(tok, "onjugate")) ||
789+
(c == 'd' && lookahead(tok, "enominator")) ||
790+
(c == 'f' && lookahead(tok, "rom_bytes")) ||
791+
(c == 'i' && (lookahead(tok, "mag") ||
792+
lookahead(tok, "s_integer"))) ||
793+
(c == 'n' && lookahead(tok, "umerator")) ||
794+
(c == 'r' && lookahead(tok, "eal")))
795+
{
796+
tok_backup(tok, c);
797+
c = '.';
798+
goto hexint;
799+
}
782800
if (Py_ISXDIGIT(c)) {
783801
c = tok_digits_tail(tok, 16);
784802
if (c == 0) {
@@ -791,6 +809,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
791809
if (c == 'p' || c == 'P') {
792810
goto exponent;
793811
}
812+
hexint:
794813
if (!verify_end_of_number(tok, c, "hexadecimal")) {
795814
return MAKE_TOKEN(ERRORTOKEN);
796815
}

Tools/jit/_stencils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ def emit_aarch64_trampoline(self, hole: Hole) -> None:
113113
f"{base + 4 * 4:x}: d61f0100 br x8",
114114
]
115115
for code in [
116-
(0xD2800008).to_bytes(4, sys.byteorder),
117-
(0xF2A00008).to_bytes(4, sys.byteorder),
118-
(0xF2C00008).to_bytes(4, sys.byteorder),
119-
(0xF2E00008).to_bytes(4, sys.byteorder),
120-
(0xD61F0100).to_bytes(4, sys.byteorder),
116+
0xD2800008.to_bytes(4, sys.byteorder),
117+
0xF2A00008.to_bytes(4, sys.byteorder),
118+
0xF2C00008.to_bytes(4, sys.byteorder),
119+
0xF2E00008.to_bytes(4, sys.byteorder),
120+
0xD61F0100.to_bytes(4, sys.byteorder),
121121
]:
122122
self.body.extend(code)
123123
for i, kind in enumerate(

0 commit comments

Comments
 (0)