12
12
import re
13
13
import time
14
14
import types
15
+ from string import ascii_letters
15
16
from typing import Dict , FrozenSet , TextIO , Tuple
16
17
17
18
import umarshal
@@ -116,6 +117,7 @@ def __init__(self, file: TextIO) -> None:
116
117
self .write ('#include "internal/pycore_gc.h"' )
117
118
self .write ('#include "internal/pycore_code.h"' )
118
119
self .write ('#include "internal/pycore_long.h"' )
120
+ self .write ('#define AS_PYOBJECT(x) ((PyObject *)(&(x)))' )
119
121
self .write ("" )
120
122
121
123
@contextlib .contextmanager
@@ -152,9 +154,9 @@ def field(self, obj: object, name: str) -> None:
152
154
153
155
def generate_bytes (self , name : str , b : bytes ) -> str :
154
156
if b == b"" :
155
- return "(PyObject *)& _Py_SINGLETON(bytes_empty)"
157
+ return "AS_PYOBJECT( _Py_SINGLETON(bytes_empty) )"
156
158
if len (b ) == 1 :
157
- return f"(PyObject *)& _Py_SINGLETON(bytes_characters[{ b [0 ]} ])"
159
+ return f"AS_PYOBJECT( _Py_SINGLETON(bytes_characters[{ b [0 ]} ]) )"
158
160
self .write ("static" )
159
161
with self .indent ():
160
162
with self .block ("struct" ):
@@ -165,11 +167,13 @@ def generate_bytes(self, name: str, b: bytes) -> str:
165
167
self .object_var_head ("PyBytes_Type" , len (b ))
166
168
self .write (".ob_shash = -1," )
167
169
self .write (f".ob_sval = { make_string_literal (b )} ," )
168
- return f"& { name } .ob_base.ob_base "
170
+ return f"AS_PYOBJECT( { name } ) "
169
171
170
172
def generate_unicode (self , name : str , s : str ) -> str :
171
173
if s in identifiers :
172
174
return f"&_Py_ID({ s } )"
175
+ if all (i in ascii_letters or i == "_" for i in s ):
176
+ name = f"const_str_{ s } "
173
177
kind , ascii = analyze_character_width (s )
174
178
if kind == PyUnicode_1BYTE_KIND :
175
179
datatype = "uint8_t"
@@ -185,7 +189,7 @@ def generate_unicode(self, name: str, s: str) -> str:
185
189
else :
186
190
self .write ("PyCompactUnicodeObject _compact;" )
187
191
self .write (f"{ datatype } _data[{ len (s )+ 1 } ];" )
188
- self .deallocs .append (f"_PyStaticUnicode_Dealloc((PyObject *)& { name } );" )
192
+ self .deallocs .append (f"_PyStaticUnicode_Dealloc(AS_PYOBJECT( { name } ) );" )
189
193
with self .block (f"{ name } =" , ";" ):
190
194
if ascii :
191
195
with self .block ("._ascii =" , "," ):
@@ -198,7 +202,7 @@ def generate_unicode(self, name: str, s: str) -> str:
198
202
self .write (".ascii = 1," )
199
203
self .write (".ready = 1," )
200
204
self .write (f"._data = { make_string_literal (s .encode ('ascii' ))} ," )
201
- return f"& { name } ._ascii.ob_base "
205
+ return f"AS_PYOBJECT( { name } ) "
202
206
else :
203
207
with self .block ("._compact =" , "," ):
204
208
with self .block ("._base =" , "," ):
@@ -224,7 +228,7 @@ def generate_unicode(self, name: str, s: str) -> str:
224
228
self .patchups .append (f" { name } ._compact._base.wstr = (wchar_t *) { name } ._data;" )
225
229
self .patchups .append (f" { name } ._compact.wstr_length = { len (s )} ;" )
226
230
self .patchups .append ("}" )
227
- return f"& { name } ._compact._base.ob_base "
231
+ return f"AS_PYOBJECT( { name } ) "
228
232
229
233
230
234
def generate_code (self , name : str , code : types .CodeType ) -> str :
@@ -282,11 +286,11 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
282
286
name_as_code = f"(PyCodeObject *)&{ name } "
283
287
self .deallocs .append (f"_PyStaticCode_Dealloc({ name_as_code } );" )
284
288
self .interns .append (f"_PyStaticCode_InternStrings({ name_as_code } )" )
285
- return f"& { name } .ob_base.ob_base "
289
+ return f"AS_PYOBJECT( { name } ) "
286
290
287
291
def generate_tuple (self , name : str , t : Tuple [object , ...]) -> str :
288
292
if len (t ) == 0 :
289
- return f"(PyObject *)& _Py_SINGLETON(tuple_empty)"
293
+ return f"AS_PYOBJECT( _Py_SINGLETON(tuple_empty) )"
290
294
items = [self .generate (f"{ name } _{ i } " , it ) for i , it in enumerate (t )]
291
295
self .write ("static" )
292
296
with self .indent ():
@@ -303,7 +307,7 @@ def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
303
307
with self .block (f".ob_item =" , "," ):
304
308
for item in items :
305
309
self .write (item + "," )
306
- return f"& { name } ._object.ob_base.ob_base "
310
+ return f"AS_PYOBJECT( { name } ._object) "
307
311
308
312
def _generate_int_for_bits (self , name : str , i : int , digit : int ) -> None :
309
313
sign = - 1 if i < 0 else 0 if i == 0 else + 1
@@ -325,7 +329,7 @@ def _generate_int_for_bits(self, name: str, i: int, digit: int) -> None:
325
329
326
330
def generate_int (self , name : str , i : int ) -> str :
327
331
if - 5 <= i <= 256 :
328
- return f"(PyObject *)& _PyLong_SMALL_INTS[_PY_NSMALLNEGINTS + { i } ]"
332
+ return f"AS_PYOBJECT( _PyLong_SMALL_INTS[_PY_NSMALLNEGINTS + { i } ]) "
329
333
if abs (i ) < 2 ** 15 :
330
334
self ._generate_int_for_bits (name , i , 2 ** 15 )
331
335
else :
@@ -338,19 +342,19 @@ def generate_int(self, name: str, i: int) -> str:
338
342
self .write ('#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"' )
339
343
self .write ("#endif" )
340
344
# If neither clause applies, it won't compile
341
- return f"& { name } .ob_base.ob_base "
345
+ return f"AS_PYOBJECT( { name } ) "
342
346
343
347
def generate_float (self , name : str , x : float ) -> str :
344
348
with self .block (f"static PyFloatObject { name } =" , ";" ):
345
349
self .object_head ("PyFloat_Type" )
346
350
self .write (f".ob_fval = { x } ," )
347
- return f"& { name } .ob_base "
351
+ return f"AS_PYOBJECT( { name } ) "
348
352
349
353
def generate_complex (self , name : str , z : complex ) -> str :
350
354
with self .block (f"static PyComplexObject { name } =" , ";" ):
351
355
self .object_head ("PyComplex_Type" )
352
356
self .write (f".cval = {{ { z .real } , { z .imag } }}," )
353
- return f"& { name } .ob_base "
357
+ return f"AS_PYOBJECT( { name } ) "
354
358
355
359
def generate_frozenset (self , name : str , fs : FrozenSet [object ]) -> str :
356
360
ret = self .generate_tuple (name , tuple (sorted (fs )))
@@ -374,7 +378,7 @@ def generate(self, name: str, obj: object) -> str:
374
378
# print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}")
375
379
return self .cache [key ]
376
380
self .misses += 1
377
- if isinstance (obj , (types .CodeType , umarshal .Code )) :
381
+ if isinstance (obj , (types .CodeType , umarshal .Code )):
378
382
val = self .generate_code (name , obj )
379
383
elif isinstance (obj , tuple ):
380
384
val = self .generate_tuple (name , obj )
@@ -411,7 +415,7 @@ def generate(self, name: str, obj: object) -> str:
411
415
_Py_get_%%NAME%%_toplevel(void)
412
416
{
413
417
%%NAME%%_do_patchups();
414
- return Py_NewRef((PyObject *) & %%NAME%%_toplevel);
418
+ return Py_NewRef(AS_PYOBJECT( %%NAME%%_toplevel) );
415
419
}
416
420
"""
417
421
0 commit comments