1212import re
1313import time
1414import types
15+ from string import ascii_letters
1516from typing import Dict , FrozenSet , TextIO , Tuple
1617
1718import umarshal
@@ -116,6 +117,7 @@ def __init__(self, file: TextIO) -> None:
116117 self .write ('#include "internal/pycore_gc.h"' )
117118 self .write ('#include "internal/pycore_code.h"' )
118119 self .write ('#include "internal/pycore_long.h"' )
120+ self .write ('#define AS_PYOBJECT(x) ((PyObject *)(&(x)))' )
119121 self .write ("" )
120122
121123 @contextlib .contextmanager
@@ -152,9 +154,9 @@ def field(self, obj: object, name: str) -> None:
152154
153155 def generate_bytes (self , name : str , b : bytes ) -> str :
154156 if b == b"" :
155- return "(PyObject *)& _Py_SINGLETON(bytes_empty)"
157+ return "AS_PYOBJECT( _Py_SINGLETON(bytes_empty) )"
156158 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 ]} ]) )"
158160 self .write ("static" )
159161 with self .indent ():
160162 with self .block ("struct" ):
@@ -165,11 +167,13 @@ def generate_bytes(self, name: str, b: bytes) -> str:
165167 self .object_var_head ("PyBytes_Type" , len (b ))
166168 self .write (".ob_shash = -1," )
167169 self .write (f".ob_sval = { make_string_literal (b )} ," )
168- return f"& { name } .ob_base.ob_base "
170+ return f"AS_PYOBJECT( { name } ) "
169171
170172 def generate_unicode (self , name : str , s : str ) -> str :
171173 if s in identifiers :
172174 return f"&_Py_ID({ s } )"
175+ if all (i in ascii_letters or i == "_" for i in s ):
176+ name = f"const_str_{ s } "
173177 kind , ascii = analyze_character_width (s )
174178 if kind == PyUnicode_1BYTE_KIND :
175179 datatype = "uint8_t"
@@ -185,7 +189,7 @@ def generate_unicode(self, name: str, s: str) -> str:
185189 else :
186190 self .write ("PyCompactUnicodeObject _compact;" )
187191 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 } ) );" )
189193 with self .block (f"{ name } =" , ";" ):
190194 if ascii :
191195 with self .block ("._ascii =" , "," ):
@@ -198,7 +202,7 @@ def generate_unicode(self, name: str, s: str) -> str:
198202 self .write (".ascii = 1," )
199203 self .write (".ready = 1," )
200204 self .write (f"._data = { make_string_literal (s .encode ('ascii' ))} ," )
201- return f"& { name } ._ascii.ob_base "
205+ return f"AS_PYOBJECT( { name } ) "
202206 else :
203207 with self .block ("._compact =" , "," ):
204208 with self .block ("._base =" , "," ):
@@ -224,7 +228,7 @@ def generate_unicode(self, name: str, s: str) -> str:
224228 self .patchups .append (f" { name } ._compact._base.wstr = (wchar_t *) { name } ._data;" )
225229 self .patchups .append (f" { name } ._compact.wstr_length = { len (s )} ;" )
226230 self .patchups .append ("}" )
227- return f"& { name } ._compact._base.ob_base "
231+ return f"AS_PYOBJECT( { name } ) "
228232
229233
230234 def generate_code (self , name : str , code : types .CodeType ) -> str :
@@ -282,11 +286,11 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
282286 name_as_code = f"(PyCodeObject *)&{ name } "
283287 self .deallocs .append (f"_PyStaticCode_Dealloc({ name_as_code } );" )
284288 self .interns .append (f"_PyStaticCode_InternStrings({ name_as_code } )" )
285- return f"& { name } .ob_base.ob_base "
289+ return f"AS_PYOBJECT( { name } ) "
286290
287291 def generate_tuple (self , name : str , t : Tuple [object , ...]) -> str :
288292 if len (t ) == 0 :
289- return f"(PyObject *)& _Py_SINGLETON(tuple_empty)"
293+ return f"AS_PYOBJECT( _Py_SINGLETON(tuple_empty) )"
290294 items = [self .generate (f"{ name } _{ i } " , it ) for i , it in enumerate (t )]
291295 self .write ("static" )
292296 with self .indent ():
@@ -303,7 +307,7 @@ def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
303307 with self .block (f".ob_item =" , "," ):
304308 for item in items :
305309 self .write (item + "," )
306- return f"& { name } ._object.ob_base.ob_base "
310+ return f"AS_PYOBJECT( { name } ._object) "
307311
308312 def _generate_int_for_bits (self , name : str , i : int , digit : int ) -> None :
309313 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:
325329
326330 def generate_int (self , name : str , i : int ) -> str :
327331 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 } ]) "
329333 if abs (i ) < 2 ** 15 :
330334 self ._generate_int_for_bits (name , i , 2 ** 15 )
331335 else :
@@ -338,19 +342,19 @@ def generate_int(self, name: str, i: int) -> str:
338342 self .write ('#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"' )
339343 self .write ("#endif" )
340344 # If neither clause applies, it won't compile
341- return f"& { name } .ob_base.ob_base "
345+ return f"AS_PYOBJECT( { name } ) "
342346
343347 def generate_float (self , name : str , x : float ) -> str :
344348 with self .block (f"static PyFloatObject { name } =" , ";" ):
345349 self .object_head ("PyFloat_Type" )
346350 self .write (f".ob_fval = { x } ," )
347- return f"& { name } .ob_base "
351+ return f"AS_PYOBJECT( { name } ) "
348352
349353 def generate_complex (self , name : str , z : complex ) -> str :
350354 with self .block (f"static PyComplexObject { name } =" , ";" ):
351355 self .object_head ("PyComplex_Type" )
352356 self .write (f".cval = {{ { z .real } , { z .imag } }}," )
353- return f"& { name } .ob_base "
357+ return f"AS_PYOBJECT( { name } ) "
354358
355359 def generate_frozenset (self , name : str , fs : FrozenSet [object ]) -> str :
356360 ret = self .generate_tuple (name , tuple (sorted (fs )))
@@ -374,7 +378,7 @@ def generate(self, name: str, obj: object) -> str:
374378 # print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}")
375379 return self .cache [key ]
376380 self .misses += 1
377- if isinstance (obj , (types .CodeType , umarshal .Code )) :
381+ if isinstance (obj , (types .CodeType , umarshal .Code )):
378382 val = self .generate_code (name , obj )
379383 elif isinstance (obj , tuple ):
380384 val = self .generate_tuple (name , obj )
@@ -411,7 +415,7 @@ def generate(self, name: str, obj: object) -> str:
411415_Py_get_%%NAME%%_toplevel(void)
412416{
413417 %%NAME%%_do_patchups();
414- return Py_NewRef((PyObject *) & %%NAME%%_toplevel);
418+ return Py_NewRef(AS_PYOBJECT( %%NAME%%_toplevel) );
415419}
416420"""
417421
0 commit comments