Code.py 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593
  1. # cython: language_level = 2
  2. # cython: auto_pickle=False
  3. #
  4. # Code output module
  5. #
  6. from __future__ import absolute_import
  7. import cython
  8. cython.declare(os=object, re=object, operator=object, textwrap=object,
  9. Template=object, Naming=object, Options=object, StringEncoding=object,
  10. Utils=object, SourceDescriptor=object, StringIOTree=object,
  11. DebugFlags=object, basestring=object, defaultdict=object,
  12. closing=object, partial=object)
  13. import os
  14. import re
  15. import shutil
  16. import sys
  17. import operator
  18. import textwrap
  19. from string import Template
  20. from functools import partial
  21. from contextlib import closing
  22. from collections import defaultdict
  23. try:
  24. import hashlib
  25. except ImportError:
  26. import md5 as hashlib
  27. from . import Naming
  28. from . import Options
  29. from . import DebugFlags
  30. from . import StringEncoding
  31. from . import Version
  32. from .. import Utils
  33. from .Scanning import SourceDescriptor
  34. from ..StringIOTree import StringIOTree
  35. try:
  36. from __builtin__ import basestring
  37. except ImportError:
  38. from builtins import str as basestring
  39. KEYWORDS_MUST_BE_BYTES = sys.version_info < (2, 7)
  40. non_portable_builtins_map = {
  41. # builtins that have different names in different Python versions
  42. 'bytes' : ('PY_MAJOR_VERSION < 3', 'str'),
  43. 'unicode' : ('PY_MAJOR_VERSION >= 3', 'str'),
  44. 'basestring' : ('PY_MAJOR_VERSION >= 3', 'str'),
  45. 'xrange' : ('PY_MAJOR_VERSION >= 3', 'range'),
  46. 'raw_input' : ('PY_MAJOR_VERSION >= 3', 'input'),
  47. }
  48. ctypedef_builtins_map = {
  49. # types of builtins in "ctypedef class" statements which we don't
  50. # import either because the names conflict with C types or because
  51. # the type simply is not exposed.
  52. 'py_int' : '&PyInt_Type',
  53. 'py_long' : '&PyLong_Type',
  54. 'py_float' : '&PyFloat_Type',
  55. 'wrapper_descriptor' : '&PyWrapperDescr_Type',
  56. }
  57. basicsize_builtins_map = {
  58. # builtins whose type has a different tp_basicsize than sizeof(...)
  59. 'PyTypeObject': 'PyHeapTypeObject',
  60. }
  61. uncachable_builtins = [
  62. # Global/builtin names that cannot be cached because they may or may not
  63. # be available at import time, for various reasons:
  64. ## - Py3.7+
  65. 'breakpoint', # might deserve an implementation in Cython
  66. ## - Py3.4+
  67. '__loader__',
  68. '__spec__',
  69. ## - Py3+
  70. 'BlockingIOError',
  71. 'BrokenPipeError',
  72. 'ChildProcessError',
  73. 'ConnectionAbortedError',
  74. 'ConnectionError',
  75. 'ConnectionRefusedError',
  76. 'ConnectionResetError',
  77. 'FileExistsError',
  78. 'FileNotFoundError',
  79. 'InterruptedError',
  80. 'IsADirectoryError',
  81. 'ModuleNotFoundError',
  82. 'NotADirectoryError',
  83. 'PermissionError',
  84. 'ProcessLookupError',
  85. 'RecursionError',
  86. 'ResourceWarning',
  87. #'StopAsyncIteration', # backported
  88. 'TimeoutError',
  89. '__build_class__',
  90. 'ascii', # might deserve an implementation in Cython
  91. #'exec', # implemented in Cython
  92. ## - Py2.7+
  93. 'memoryview',
  94. ## - platform specific
  95. 'WindowsError',
  96. ## - others
  97. '_', # e.g. used by gettext
  98. ]
  99. special_py_methods = set([
  100. '__cinit__', '__dealloc__', '__richcmp__', '__next__',
  101. '__await__', '__aiter__', '__anext__',
  102. '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__',
  103. '__getcharbuffer__', '__getbuffer__', '__releasebuffer__'
  104. ])
  105. modifier_output_mapper = {
  106. 'inline': 'CYTHON_INLINE'
  107. }.get
  108. class IncludeCode(object):
  109. """
  110. An include file and/or verbatim C code to be included in the
  111. generated sources.
  112. """
  113. # attributes:
  114. #
  115. # pieces {order: unicode}: pieces of C code to be generated.
  116. # For the included file, the key "order" is zero.
  117. # For verbatim include code, the "order" is the "order"
  118. # attribute of the original IncludeCode where this piece
  119. # of C code was first added. This is needed to prevent
  120. # duplication if the same include code is found through
  121. # multiple cimports.
  122. # location int: where to put this include in the C sources, one
  123. # of the constants INITIAL, EARLY, LATE
  124. # order int: sorting order (automatically set by increasing counter)
  125. # Constants for location. If the same include occurs with different
  126. # locations, the earliest one takes precedense.
  127. INITIAL = 0
  128. EARLY = 1
  129. LATE = 2
  130. counter = 1 # Counter for "order"
  131. def __init__(self, include=None, verbatim=None, late=True, initial=False):
  132. self.order = self.counter
  133. type(self).counter += 1
  134. self.pieces = {}
  135. if include:
  136. if include[0] == '<' and include[-1] == '>':
  137. self.pieces[0] = u'#include {0}'.format(include)
  138. late = False # system include is never late
  139. else:
  140. self.pieces[0] = u'#include "{0}"'.format(include)
  141. if verbatim:
  142. self.pieces[self.order] = verbatim
  143. if initial:
  144. self.location = self.INITIAL
  145. elif late:
  146. self.location = self.LATE
  147. else:
  148. self.location = self.EARLY
  149. def dict_update(self, d, key):
  150. """
  151. Insert `self` in dict `d` with key `key`. If that key already
  152. exists, update the attributes of the existing value with `self`.
  153. """
  154. if key in d:
  155. other = d[key]
  156. other.location = min(self.location, other.location)
  157. other.pieces.update(self.pieces)
  158. else:
  159. d[key] = self
  160. def sortkey(self):
  161. return self.order
  162. def mainpiece(self):
  163. """
  164. Return the main piece of C code, corresponding to the include
  165. file. If there was no include file, return None.
  166. """
  167. return self.pieces.get(0)
  168. def write(self, code):
  169. # Write values of self.pieces dict, sorted by the keys
  170. for k in sorted(self.pieces):
  171. code.putln(self.pieces[k])
  172. def get_utility_dir():
  173. # make this a function and not global variables:
  174. # http://trac.cython.org/cython_trac/ticket/475
  175. Cython_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  176. return os.path.join(Cython_dir, "Utility")
  177. class UtilityCodeBase(object):
  178. """
  179. Support for loading utility code from a file.
  180. Code sections in the file can be specified as follows:
  181. ##### MyUtility.proto #####
  182. [proto declarations]
  183. ##### MyUtility.init #####
  184. [code run at module initialization]
  185. ##### MyUtility #####
  186. #@requires: MyOtherUtility
  187. #@substitute: naming
  188. [definitions]
  189. for prototypes and implementation respectively. For non-python or
  190. -cython files backslashes should be used instead. 5 to 30 comment
  191. characters may be used on either side.
  192. If the @cname decorator is not used and this is a CythonUtilityCode,
  193. one should pass in the 'name' keyword argument to be used for name
  194. mangling of such entries.
  195. """
  196. is_cython_utility = False
  197. _utility_cache = {}
  198. @classmethod
  199. def _add_utility(cls, utility, type, lines, begin_lineno, tags=None):
  200. if utility is None:
  201. return
  202. code = '\n'.join(lines)
  203. if tags and 'substitute' in tags and tags['substitute'] == set(['naming']):
  204. del tags['substitute']
  205. try:
  206. code = Template(code).substitute(vars(Naming))
  207. except (KeyError, ValueError) as e:
  208. raise RuntimeError("Error parsing templated utility code of type '%s' at line %d: %s" % (
  209. type, begin_lineno, e))
  210. # remember correct line numbers at least until after templating
  211. code = '\n' * begin_lineno + code
  212. if type == 'proto':
  213. utility[0] = code
  214. elif type == 'impl':
  215. utility[1] = code
  216. else:
  217. all_tags = utility[2]
  218. if KEYWORDS_MUST_BE_BYTES:
  219. type = type.encode('ASCII')
  220. all_tags[type] = code
  221. if tags:
  222. all_tags = utility[2]
  223. for name, values in tags.items():
  224. if KEYWORDS_MUST_BE_BYTES:
  225. name = name.encode('ASCII')
  226. all_tags.setdefault(name, set()).update(values)
  227. @classmethod
  228. def load_utilities_from_file(cls, path):
  229. utilities = cls._utility_cache.get(path)
  230. if utilities:
  231. return utilities
  232. filename = os.path.join(get_utility_dir(), path)
  233. _, ext = os.path.splitext(path)
  234. if ext in ('.pyx', '.py', '.pxd', '.pxi'):
  235. comment = '#'
  236. strip_comments = partial(re.compile(r'^\s*#(?!\s*cython\s*:).*').sub, '')
  237. rstrip = StringEncoding._unicode.rstrip
  238. else:
  239. comment = '/'
  240. strip_comments = partial(re.compile(r'^\s*//.*|/\*[^*]*\*/').sub, '')
  241. rstrip = partial(re.compile(r'\s+(\\?)$').sub, r'\1')
  242. match_special = re.compile(
  243. (r'^%(C)s{5,30}\s*(?P<name>(?:\w|\.)+)\s*%(C)s{5,30}|'
  244. r'^%(C)s+@(?P<tag>\w+)\s*:\s*(?P<value>(?:\w|[.:])+)') %
  245. {'C': comment}).match
  246. match_type = re.compile(r'(.+)[.](proto(?:[.]\S+)?|impl|init|cleanup)$').match
  247. with closing(Utils.open_source_file(filename, encoding='UTF-8')) as f:
  248. all_lines = f.readlines()
  249. utilities = defaultdict(lambda: [None, None, {}])
  250. lines = []
  251. tags = defaultdict(set)
  252. utility = type = None
  253. begin_lineno = 0
  254. for lineno, line in enumerate(all_lines):
  255. m = match_special(line)
  256. if m:
  257. if m.group('name'):
  258. cls._add_utility(utility, type, lines, begin_lineno, tags)
  259. begin_lineno = lineno + 1
  260. del lines[:]
  261. tags.clear()
  262. name = m.group('name')
  263. mtype = match_type(name)
  264. if mtype:
  265. name, type = mtype.groups()
  266. else:
  267. type = 'impl'
  268. utility = utilities[name]
  269. else:
  270. tags[m.group('tag')].add(m.group('value'))
  271. lines.append('') # keep line number correct
  272. else:
  273. lines.append(rstrip(strip_comments(line)))
  274. if utility is None:
  275. raise ValueError("Empty utility code file")
  276. # Don't forget to add the last utility code
  277. cls._add_utility(utility, type, lines, begin_lineno, tags)
  278. utilities = dict(utilities) # un-defaultdict-ify
  279. cls._utility_cache[path] = utilities
  280. return utilities
  281. @classmethod
  282. def load(cls, util_code_name, from_file=None, **kwargs):
  283. """
  284. Load utility code from a file specified by from_file (relative to
  285. Cython/Utility) and name util_code_name. If from_file is not given,
  286. load it from the file util_code_name.*. There should be only one
  287. file matched by this pattern.
  288. """
  289. if '::' in util_code_name:
  290. from_file, util_code_name = util_code_name.rsplit('::', 1)
  291. if not from_file:
  292. utility_dir = get_utility_dir()
  293. prefix = util_code_name + '.'
  294. try:
  295. listing = os.listdir(utility_dir)
  296. except OSError:
  297. # XXX the code below assumes as 'zipimport.zipimporter' instance
  298. # XXX should be easy to generalize, but too lazy right now to write it
  299. import zipfile
  300. global __loader__
  301. loader = __loader__
  302. archive = loader.archive
  303. with closing(zipfile.ZipFile(archive)) as fileobj:
  304. listing = [os.path.basename(name)
  305. for name in fileobj.namelist()
  306. if os.path.join(archive, name).startswith(utility_dir)]
  307. files = [filename for filename in listing
  308. if filename.startswith(prefix)]
  309. if not files:
  310. raise ValueError("No match found for utility code " + util_code_name)
  311. if len(files) > 1:
  312. raise ValueError("More than one filename match found for utility code " + util_code_name)
  313. from_file = files[0]
  314. utilities = cls.load_utilities_from_file(from_file)
  315. proto, impl, tags = utilities[util_code_name]
  316. if tags:
  317. orig_kwargs = kwargs.copy()
  318. for name, values in tags.items():
  319. if name in kwargs:
  320. continue
  321. # only pass lists when we have to: most argument expect one value or None
  322. if name == 'requires':
  323. if orig_kwargs:
  324. values = [cls.load(dep, from_file, **orig_kwargs)
  325. for dep in sorted(values)]
  326. else:
  327. # dependencies are rarely unique, so use load_cached() when we can
  328. values = [cls.load_cached(dep, from_file)
  329. for dep in sorted(values)]
  330. elif not values:
  331. values = None
  332. elif len(values) == 1:
  333. values = list(values)[0]
  334. kwargs[name] = values
  335. if proto is not None:
  336. kwargs['proto'] = proto
  337. if impl is not None:
  338. kwargs['impl'] = impl
  339. if 'name' not in kwargs:
  340. kwargs['name'] = util_code_name
  341. if 'file' not in kwargs and from_file:
  342. kwargs['file'] = from_file
  343. return cls(**kwargs)
  344. @classmethod
  345. def load_cached(cls, utility_code_name, from_file=None, __cache={}):
  346. """
  347. Calls .load(), but using a per-type cache based on utility name and file name.
  348. """
  349. key = (cls, from_file, utility_code_name)
  350. try:
  351. return __cache[key]
  352. except KeyError:
  353. pass
  354. code = __cache[key] = cls.load(utility_code_name, from_file)
  355. return code
  356. @classmethod
  357. def load_as_string(cls, util_code_name, from_file=None, **kwargs):
  358. """
  359. Load a utility code as a string. Returns (proto, implementation)
  360. """
  361. util = cls.load(util_code_name, from_file, **kwargs)
  362. proto, impl = util.proto, util.impl
  363. return util.format_code(proto), util.format_code(impl)
  364. def format_code(self, code_string, replace_empty_lines=re.compile(r'\n\n+').sub):
  365. """
  366. Format a code section for output.
  367. """
  368. if code_string:
  369. code_string = replace_empty_lines('\n', code_string.strip()) + '\n\n'
  370. return code_string
  371. def __str__(self):
  372. return "<%s(%s)>" % (type(self).__name__, self.name)
  373. def get_tree(self, **kwargs):
  374. pass
  375. def __deepcopy__(self, memodict=None):
  376. # No need to deep-copy utility code since it's essentially immutable.
  377. return self
  378. class UtilityCode(UtilityCodeBase):
  379. """
  380. Stores utility code to add during code generation.
  381. See GlobalState.put_utility_code.
  382. hashes/equals by instance
  383. proto C prototypes
  384. impl implementation code
  385. init code to call on module initialization
  386. requires utility code dependencies
  387. proto_block the place in the resulting file where the prototype should
  388. end up
  389. name name of the utility code (or None)
  390. file filename of the utility code file this utility was loaded
  391. from (or None)
  392. """
  393. def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None,
  394. proto_block='utility_code_proto', name=None, file=None):
  395. # proto_block: Which code block to dump prototype in. See GlobalState.
  396. self.proto = proto
  397. self.impl = impl
  398. self.init = init
  399. self.cleanup = cleanup
  400. self.requires = requires
  401. self._cache = {}
  402. self.specialize_list = []
  403. self.proto_block = proto_block
  404. self.name = name
  405. self.file = file
  406. def __hash__(self):
  407. return hash((self.proto, self.impl))
  408. def __eq__(self, other):
  409. if self is other:
  410. return True
  411. self_type, other_type = type(self), type(other)
  412. if self_type is not other_type and not (isinstance(other, self_type) or isinstance(self, other_type)):
  413. return False
  414. self_proto = getattr(self, 'proto', None)
  415. other_proto = getattr(other, 'proto', None)
  416. return (self_proto, self.impl) == (other_proto, other.impl)
  417. def none_or_sub(self, s, context):
  418. """
  419. Format a string in this utility code with context. If None, do nothing.
  420. """
  421. if s is None:
  422. return None
  423. return s % context
  424. def specialize(self, pyrex_type=None, **data):
  425. # Dicts aren't hashable...
  426. if pyrex_type is not None:
  427. data['type'] = pyrex_type.empty_declaration_code()
  428. data['type_name'] = pyrex_type.specialization_name()
  429. key = tuple(sorted(data.items()))
  430. try:
  431. return self._cache[key]
  432. except KeyError:
  433. if self.requires is None:
  434. requires = None
  435. else:
  436. requires = [r.specialize(data) for r in self.requires]
  437. s = self._cache[key] = UtilityCode(
  438. self.none_or_sub(self.proto, data),
  439. self.none_or_sub(self.impl, data),
  440. self.none_or_sub(self.init, data),
  441. self.none_or_sub(self.cleanup, data),
  442. requires,
  443. self.proto_block)
  444. self.specialize_list.append(s)
  445. return s
  446. def inject_string_constants(self, impl, output):
  447. """Replace 'PYIDENT("xyz")' by a constant Python identifier cname.
  448. """
  449. if 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl:
  450. return False, impl
  451. replacements = {}
  452. def externalise(matchobj):
  453. key = matchobj.groups()
  454. try:
  455. cname = replacements[key]
  456. except KeyError:
  457. str_type, name = key
  458. cname = replacements[key] = output.get_py_string_const(
  459. StringEncoding.EncodedString(name), identifier=str_type == 'IDENT').cname
  460. return cname
  461. impl = re.sub(r'PY(IDENT|UNICODE)\("([^"]+)"\)', externalise, impl)
  462. assert 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl
  463. return True, impl
  464. def inject_unbound_methods(self, impl, output):
  465. """Replace 'UNBOUND_METHOD(type, "name")' by a constant Python identifier cname.
  466. """
  467. if 'CALL_UNBOUND_METHOD(' not in impl:
  468. return False, impl
  469. def externalise(matchobj):
  470. type_cname, method_name, obj_cname, args = matchobj.groups()
  471. args = [arg.strip() for arg in args[1:].split(',')] if args else []
  472. assert len(args) < 3, "CALL_UNBOUND_METHOD() does not support %d call arguments" % len(args)
  473. return output.cached_unbound_method_call_code(obj_cname, type_cname, method_name, args)
  474. impl = re.sub(
  475. r'CALL_UNBOUND_METHOD\('
  476. r'([a-zA-Z_]+),' # type cname
  477. r'\s*"([^"]+)",' # method name
  478. r'\s*([^),]+)' # object cname
  479. r'((?:,\s*[^),]+)*)' # args*
  480. r'\)', externalise, impl)
  481. assert 'CALL_UNBOUND_METHOD(' not in impl
  482. return True, impl
  483. def wrap_c_strings(self, impl):
  484. """Replace CSTRING('''xyz''') by a C compatible string
  485. """
  486. if 'CSTRING(' not in impl:
  487. return impl
  488. def split_string(matchobj):
  489. content = matchobj.group(1).replace('"', '\042')
  490. return ''.join(
  491. '"%s\\n"\n' % line if not line.endswith('\\') or line.endswith('\\\\') else '"%s"\n' % line[:-1]
  492. for line in content.splitlines())
  493. impl = re.sub(r'CSTRING\(\s*"""([^"]*(?:"[^"]+)*)"""\s*\)', split_string, impl)
  494. assert 'CSTRING(' not in impl
  495. return impl
  496. def put_code(self, output):
  497. if self.requires:
  498. for dependency in self.requires:
  499. output.use_utility_code(dependency)
  500. if self.proto:
  501. writer = output[self.proto_block]
  502. writer.putln("/* %s.proto */" % self.name)
  503. writer.put_or_include(
  504. self.format_code(self.proto), '%s_proto' % self.name)
  505. if self.impl:
  506. impl = self.format_code(self.wrap_c_strings(self.impl))
  507. is_specialised1, impl = self.inject_string_constants(impl, output)
  508. is_specialised2, impl = self.inject_unbound_methods(impl, output)
  509. writer = output['utility_code_def']
  510. writer.putln("/* %s */" % self.name)
  511. if not (is_specialised1 or is_specialised2):
  512. # no module specific adaptations => can be reused
  513. writer.put_or_include(impl, '%s_impl' % self.name)
  514. else:
  515. writer.put(impl)
  516. if self.init:
  517. writer = output['init_globals']
  518. writer.putln("/* %s.init */" % self.name)
  519. if isinstance(self.init, basestring):
  520. writer.put(self.format_code(self.init))
  521. else:
  522. self.init(writer, output.module_pos)
  523. writer.putln(writer.error_goto_if_PyErr(output.module_pos))
  524. writer.putln()
  525. if self.cleanup and Options.generate_cleanup_code:
  526. writer = output['cleanup_globals']
  527. writer.putln("/* %s.cleanup */" % self.name)
  528. if isinstance(self.cleanup, basestring):
  529. writer.put_or_include(
  530. self.format_code(self.cleanup),
  531. '%s_cleanup' % self.name)
  532. else:
  533. self.cleanup(writer, output.module_pos)
  534. def sub_tempita(s, context, file=None, name=None):
  535. "Run tempita on string s with given context."
  536. if not s:
  537. return None
  538. if file:
  539. context['__name'] = "%s:%s" % (file, name)
  540. elif name:
  541. context['__name'] = name
  542. from ..Tempita import sub
  543. return sub(s, **context)
  544. class TempitaUtilityCode(UtilityCode):
  545. def __init__(self, name=None, proto=None, impl=None, init=None, file=None, context=None, **kwargs):
  546. if context is None:
  547. context = {}
  548. proto = sub_tempita(proto, context, file, name)
  549. impl = sub_tempita(impl, context, file, name)
  550. init = sub_tempita(init, context, file, name)
  551. super(TempitaUtilityCode, self).__init__(
  552. proto, impl, init=init, name=name, file=file, **kwargs)
  553. @classmethod
  554. def load_cached(cls, utility_code_name, from_file=None, context=None, __cache={}):
  555. context_key = tuple(sorted(context.items())) if context else None
  556. assert hash(context_key) is not None # raise TypeError if not hashable
  557. key = (cls, from_file, utility_code_name, context_key)
  558. try:
  559. return __cache[key]
  560. except KeyError:
  561. pass
  562. code = __cache[key] = cls.load(utility_code_name, from_file, context=context)
  563. return code
  564. def none_or_sub(self, s, context):
  565. """
  566. Format a string in this utility code with context. If None, do nothing.
  567. """
  568. if s is None:
  569. return None
  570. return sub_tempita(s, context, self.file, self.name)
  571. class LazyUtilityCode(UtilityCodeBase):
  572. """
  573. Utility code that calls a callback with the root code writer when
  574. available. Useful when you only have 'env' but not 'code'.
  575. """
  576. __name__ = '<lazy>'
  577. requires = None
  578. def __init__(self, callback):
  579. self.callback = callback
  580. def put_code(self, globalstate):
  581. utility = self.callback(globalstate.rootwriter)
  582. globalstate.use_utility_code(utility)
  583. class FunctionState(object):
  584. # return_label string function return point label
  585. # error_label string error catch point label
  586. # continue_label string loop continue point label
  587. # break_label string loop break point label
  588. # return_from_error_cleanup_label string
  589. # label_counter integer counter for naming labels
  590. # in_try_finally boolean inside try of try...finally
  591. # exc_vars (string * 3) exception variables for reraise, or None
  592. # can_trace boolean line tracing is supported in the current context
  593. # scope Scope the scope object of the current function
  594. # Not used for now, perhaps later
  595. def __init__(self, owner, names_taken=set(), scope=None):
  596. self.names_taken = names_taken
  597. self.owner = owner
  598. self.scope = scope
  599. self.error_label = None
  600. self.label_counter = 0
  601. self.labels_used = set()
  602. self.return_label = self.new_label()
  603. self.new_error_label()
  604. self.continue_label = None
  605. self.break_label = None
  606. self.yield_labels = []
  607. self.in_try_finally = 0
  608. self.exc_vars = None
  609. self.current_except = None
  610. self.can_trace = False
  611. self.gil_owned = True
  612. self.temps_allocated = [] # of (name, type, manage_ref, static)
  613. self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
  614. self.temps_used_type = {} # name -> (type, manage_ref)
  615. self.zombie_temps = set() # temps that must not be reused after release
  616. self.temp_counter = 0
  617. self.closure_temps = None
  618. # This is used to collect temporaries, useful to find out which temps
  619. # need to be privatized in parallel sections
  620. self.collect_temps_stack = []
  621. # This is used for the error indicator, which needs to be local to the
  622. # function. It used to be global, which relies on the GIL being held.
  623. # However, exceptions may need to be propagated through 'nogil'
  624. # sections, in which case we introduce a race condition.
  625. self.should_declare_error_indicator = False
  626. self.uses_error_indicator = False
  627. # safety checks
  628. def validate_exit(self):
  629. # validate that all allocated temps have been freed
  630. if self.temps_allocated:
  631. leftovers = self.temps_in_use()
  632. if leftovers:
  633. msg = "TEMPGUARD: Temps left over at end of '%s': %s" % (self.scope.name, ', '.join([
  634. '%s [%s]' % (name, ctype)
  635. for name, ctype, is_pytemp in sorted(leftovers)]),
  636. )
  637. #print(msg)
  638. raise RuntimeError(msg)
  639. # labels
  640. def new_label(self, name=None):
  641. n = self.label_counter
  642. self.label_counter = n + 1
  643. label = "%s%d" % (Naming.label_prefix, n)
  644. if name is not None:
  645. label += '_' + name
  646. return label
  647. def new_yield_label(self, expr_type='yield'):
  648. label = self.new_label('resume_from_%s' % expr_type)
  649. num_and_label = (len(self.yield_labels) + 1, label)
  650. self.yield_labels.append(num_and_label)
  651. return num_and_label
  652. def new_error_label(self):
  653. old_err_lbl = self.error_label
  654. self.error_label = self.new_label('error')
  655. return old_err_lbl
  656. def get_loop_labels(self):
  657. return (
  658. self.continue_label,
  659. self.break_label)
  660. def set_loop_labels(self, labels):
  661. (self.continue_label,
  662. self.break_label) = labels
  663. def new_loop_labels(self):
  664. old_labels = self.get_loop_labels()
  665. self.set_loop_labels(
  666. (self.new_label("continue"),
  667. self.new_label("break")))
  668. return old_labels
  669. def get_all_labels(self):
  670. return (
  671. self.continue_label,
  672. self.break_label,
  673. self.return_label,
  674. self.error_label)
  675. def set_all_labels(self, labels):
  676. (self.continue_label,
  677. self.break_label,
  678. self.return_label,
  679. self.error_label) = labels
  680. def all_new_labels(self):
  681. old_labels = self.get_all_labels()
  682. new_labels = []
  683. for old_label, name in zip(old_labels, ['continue', 'break', 'return', 'error']):
  684. if old_label:
  685. new_labels.append(self.new_label(name))
  686. else:
  687. new_labels.append(old_label)
  688. self.set_all_labels(new_labels)
  689. return old_labels
  690. def use_label(self, lbl):
  691. self.labels_used.add(lbl)
  692. def label_used(self, lbl):
  693. return lbl in self.labels_used
  694. # temp handling
  695. def allocate_temp(self, type, manage_ref, static=False, reusable=True):
  696. """
  697. Allocates a temporary (which may create a new one or get a previously
  698. allocated and released one of the same type). Type is simply registered
  699. and handed back, but will usually be a PyrexType.
  700. If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
  701. True, the temp will be decref-ed on return statements and in exception
  702. handling clauses. Otherwise the caller has to deal with any reference
  703. counting of the variable.
  704. If not type.is_pyobject, then manage_ref will be ignored, but it
  705. still has to be passed. It is recommended to pass False by convention
  706. if it is known that type will never be a Python object.
  707. static=True marks the temporary declaration with "static".
  708. This is only used when allocating backing store for a module-level
  709. C array literals.
  710. if reusable=False, the temp will not be reused after release.
  711. A C string referring to the variable is returned.
  712. """
  713. if type.is_const and not type.is_reference:
  714. type = type.const_base_type
  715. elif type.is_reference and not type.is_fake_reference:
  716. type = type.ref_base_type
  717. elif type.is_cfunction:
  718. from . import PyrexTypes
  719. type = PyrexTypes.c_ptr_type(type) # A function itself isn't an l-value
  720. if not type.is_pyobject and not type.is_memoryviewslice:
  721. # Make manage_ref canonical, so that manage_ref will always mean
  722. # a decref is needed.
  723. manage_ref = False
  724. freelist = self.temps_free.get((type, manage_ref))
  725. if reusable and freelist is not None and freelist[0]:
  726. result = freelist[0].pop()
  727. freelist[1].remove(result)
  728. else:
  729. while True:
  730. self.temp_counter += 1
  731. result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
  732. if result not in self.names_taken: break
  733. self.temps_allocated.append((result, type, manage_ref, static))
  734. if not reusable:
  735. self.zombie_temps.add(result)
  736. self.temps_used_type[result] = (type, manage_ref)
  737. if DebugFlags.debug_temp_code_comments:
  738. self.owner.putln("/* %s allocated (%s)%s */" % (result, type, "" if reusable else " - zombie"))
  739. if self.collect_temps_stack:
  740. self.collect_temps_stack[-1].add((result, type))
  741. return result
  742. def release_temp(self, name):
  743. """
  744. Releases a temporary so that it can be reused by other code needing
  745. a temp of the same type.
  746. """
  747. type, manage_ref = self.temps_used_type[name]
  748. freelist = self.temps_free.get((type, manage_ref))
  749. if freelist is None:
  750. freelist = ([], set()) # keep order in list and make lookups in set fast
  751. self.temps_free[(type, manage_ref)] = freelist
  752. if name in freelist[1]:
  753. raise RuntimeError("Temp %s freed twice!" % name)
  754. if name not in self.zombie_temps:
  755. freelist[0].append(name)
  756. freelist[1].add(name)
  757. if DebugFlags.debug_temp_code_comments:
  758. self.owner.putln("/* %s released %s*/" % (
  759. name, " - zombie" if name in self.zombie_temps else ""))
  760. def temps_in_use(self):
  761. """Return a list of (cname,type,manage_ref) tuples of temp names and their type
  762. that are currently in use.
  763. """
  764. used = []
  765. for name, type, manage_ref, static in self.temps_allocated:
  766. freelist = self.temps_free.get((type, manage_ref))
  767. if freelist is None or name not in freelist[1]:
  768. used.append((name, type, manage_ref and type.is_pyobject))
  769. return used
  770. def temps_holding_reference(self):
  771. """Return a list of (cname,type) tuples of temp names and their type
  772. that are currently in use. This includes only temps of a
  773. Python object type which owns its reference.
  774. """
  775. return [(name, type)
  776. for name, type, manage_ref in self.temps_in_use()
  777. if manage_ref and type.is_pyobject]
  778. def all_managed_temps(self):
  779. """Return a list of (cname, type) tuples of refcount-managed Python objects.
  780. """
  781. return [(cname, type)
  782. for cname, type, manage_ref, static in self.temps_allocated
  783. if manage_ref]
  784. def all_free_managed_temps(self):
  785. """Return a list of (cname, type) tuples of refcount-managed Python
  786. objects that are not currently in use. This is used by
  787. try-except and try-finally blocks to clean up temps in the
  788. error case.
  789. """
  790. return sorted([ # Enforce deterministic order.
  791. (cname, type)
  792. for (type, manage_ref), freelist in self.temps_free.items() if manage_ref
  793. for cname in freelist[0]
  794. ])
  795. def start_collecting_temps(self):
  796. """
  797. Useful to find out which temps were used in a code block
  798. """
  799. self.collect_temps_stack.append(set())
  800. def stop_collecting_temps(self):
  801. return self.collect_temps_stack.pop()
  802. def init_closure_temps(self, scope):
  803. self.closure_temps = ClosureTempAllocator(scope)
  804. class NumConst(object):
  805. """Global info about a Python number constant held by GlobalState.
  806. cname string
  807. value string
  808. py_type string int, long, float
  809. value_code string evaluation code if different from value
  810. """
  811. def __init__(self, cname, value, py_type, value_code=None):
  812. self.cname = cname
  813. self.value = value
  814. self.py_type = py_type
  815. self.value_code = value_code or value
  816. class PyObjectConst(object):
  817. """Global info about a generic constant held by GlobalState.
  818. """
  819. # cname string
  820. # type PyrexType
  821. def __init__(self, cname, type):
  822. self.cname = cname
  823. self.type = type
  824. cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
  825. replace_identifier=object, find_alphanums=object)
  826. possible_unicode_identifier = re.compile(br"(?![0-9])\w+$".decode('ascii'), re.U).match
  827. possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
  828. replace_identifier = re.compile(r'[^a-zA-Z0-9_]+').sub
  829. find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
  830. class StringConst(object):
  831. """Global info about a C string constant held by GlobalState.
  832. """
  833. # cname string
  834. # text EncodedString or BytesLiteral
  835. # py_strings {(identifier, encoding) : PyStringConst}
  836. def __init__(self, cname, text, byte_string):
  837. self.cname = cname
  838. self.text = text
  839. self.escaped_value = StringEncoding.escape_byte_string(byte_string)
  840. self.py_strings = None
  841. self.py_versions = []
  842. def add_py_version(self, version):
  843. if not version:
  844. self.py_versions = [2, 3]
  845. elif version not in self.py_versions:
  846. self.py_versions.append(version)
  847. def get_py_string_const(self, encoding, identifier=None,
  848. is_str=False, py3str_cstring=None):
  849. py_strings = self.py_strings
  850. text = self.text
  851. is_str = bool(identifier or is_str)
  852. is_unicode = encoding is None and not is_str
  853. if encoding is None:
  854. # unicode string
  855. encoding_key = None
  856. else:
  857. # bytes or str
  858. encoding = encoding.lower()
  859. if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
  860. encoding = None
  861. encoding_key = None
  862. else:
  863. encoding_key = ''.join(find_alphanums(encoding))
  864. key = (is_str, is_unicode, encoding_key, py3str_cstring)
  865. if py_strings is not None:
  866. try:
  867. return py_strings[key]
  868. except KeyError:
  869. pass
  870. else:
  871. self.py_strings = {}
  872. if identifier:
  873. intern = True
  874. elif identifier is None:
  875. if isinstance(text, bytes):
  876. intern = bool(possible_bytes_identifier(text))
  877. else:
  878. intern = bool(possible_unicode_identifier(text))
  879. else:
  880. intern = False
  881. if intern:
  882. prefix = Naming.interned_prefixes['str']
  883. else:
  884. prefix = Naming.py_const_prefix
  885. if encoding_key:
  886. encoding_prefix = '_%s' % encoding_key
  887. else:
  888. encoding_prefix = ''
  889. pystring_cname = "%s%s%s_%s" % (
  890. prefix,
  891. (is_str and 's') or (is_unicode and 'u') or 'b',
  892. encoding_prefix,
  893. self.cname[len(Naming.const_prefix):])
  894. py_string = PyStringConst(
  895. pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
  896. self.py_strings[key] = py_string
  897. return py_string
  898. class PyStringConst(object):
  899. """Global info about a Python string constant held by GlobalState.
  900. """
  901. # cname string
  902. # py3str_cstring string
  903. # encoding string
  904. # intern boolean
  905. # is_unicode boolean
  906. # is_str boolean
  907. def __init__(self, cname, encoding, is_unicode, is_str=False,
  908. py3str_cstring=None, intern=False):
  909. self.cname = cname
  910. self.py3str_cstring = py3str_cstring
  911. self.encoding = encoding
  912. self.is_str = is_str
  913. self.is_unicode = is_unicode
  914. self.intern = intern
  915. def __lt__(self, other):
  916. return self.cname < other.cname
  917. class GlobalState(object):
  918. # filename_table {string : int} for finding filename table indexes
  919. # filename_list [string] filenames in filename table order
  920. # input_file_contents dict contents (=list of lines) of any file that was used as input
  921. # to create this output C code. This is
  922. # used to annotate the comments.
  923. #
  924. # utility_codes set IDs of used utility code (to avoid reinsertion)
  925. #
  926. # declared_cnames {string:Entry} used in a transition phase to merge pxd-declared
  927. # constants etc. into the pyx-declared ones (i.e,
  928. # check if constants are already added).
  929. # In time, hopefully the literals etc. will be
  930. # supplied directly instead.
  931. #
  932. # const_cnames_used dict global counter for unique constant identifiers
  933. #
  934. # parts {string:CCodeWriter}
  935. # interned_strings
  936. # consts
  937. # interned_nums
  938. # directives set Temporary variable used to track
  939. # the current set of directives in the code generation
  940. # process.
  941. directives = {}
  942. code_layout = [
  943. 'h_code',
  944. 'filename_table',
  945. 'utility_code_proto_before_types',
  946. 'numeric_typedefs', # Let these detailed individual parts stay!,
  947. 'complex_type_declarations', # as the proper solution is to make a full DAG...
  948. 'type_declarations', # More coarse-grained blocks would simply hide
  949. 'utility_code_proto', # the ugliness, not fix it
  950. 'module_declarations',
  951. 'typeinfo',
  952. 'before_global_var',
  953. 'global_var',
  954. 'string_decls',
  955. 'decls',
  956. 'late_includes',
  957. 'all_the_rest',
  958. 'pystring_table',
  959. 'cached_builtins',
  960. 'cached_constants',
  961. 'init_globals',
  962. 'init_module',
  963. 'cleanup_globals',
  964. 'cleanup_module',
  965. 'main_method',
  966. 'utility_code_def',
  967. 'end'
  968. ]
  969. def __init__(self, writer, module_node, code_config, common_utility_include_dir=None):
  970. self.filename_table = {}
  971. self.filename_list = []
  972. self.input_file_contents = {}
  973. self.utility_codes = set()
  974. self.declared_cnames = {}
  975. self.in_utility_code_generation = False
  976. self.code_config = code_config
  977. self.common_utility_include_dir = common_utility_include_dir
  978. self.parts = {}
  979. self.module_node = module_node # because some utility code generation needs it
  980. # (generating backwards-compatible Get/ReleaseBuffer
  981. self.const_cnames_used = {}
  982. self.string_const_index = {}
  983. self.dedup_const_index = {}
  984. self.pyunicode_ptr_const_index = {}
  985. self.num_const_index = {}
  986. self.py_constants = []
  987. self.cached_cmethods = {}
  988. self.initialised_constants = set()
  989. writer.set_global_state(self)
  990. self.rootwriter = writer
  991. def initialize_main_c_code(self):
  992. rootwriter = self.rootwriter
  993. for part in self.code_layout:
  994. self.parts[part] = rootwriter.insertion_point()
  995. if not Options.cache_builtins:
  996. del self.parts['cached_builtins']
  997. else:
  998. w = self.parts['cached_builtins']
  999. w.enter_cfunc_scope()
  1000. w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {")
  1001. w = self.parts['cached_constants']
  1002. w.enter_cfunc_scope()
  1003. w.putln("")
  1004. w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {")
  1005. w.put_declare_refcount_context()
  1006. w.put_setup_refcount_context("__Pyx_InitCachedConstants")
  1007. w = self.parts['init_globals']
  1008. w.enter_cfunc_scope()
  1009. w.putln("")
  1010. w.putln("static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) {")
  1011. if not Options.generate_cleanup_code:
  1012. del self.parts['cleanup_globals']
  1013. else:
  1014. w = self.parts['cleanup_globals']
  1015. w.enter_cfunc_scope()
  1016. w.putln("")
  1017. w.putln("static CYTHON_SMALL_CODE void __Pyx_CleanupGlobals(void) {")
  1018. code = self.parts['utility_code_proto']
  1019. code.putln("")
  1020. code.putln("/* --- Runtime support code (head) --- */")
  1021. code = self.parts['utility_code_def']
  1022. if self.code_config.emit_linenums:
  1023. code.write('\n#line 1 "cython_utility"\n')
  1024. code.putln("")
  1025. code.putln("/* --- Runtime support code --- */")
  1026. def finalize_main_c_code(self):
  1027. self.close_global_decls()
  1028. #
  1029. # utility_code_def
  1030. #
  1031. code = self.parts['utility_code_def']
  1032. util = TempitaUtilityCode.load_cached("TypeConversions", "TypeConversion.c")
  1033. code.put(util.format_code(util.impl))
  1034. code.putln("")
  1035. def __getitem__(self, key):
  1036. return self.parts[key]
  1037. #
  1038. # Global constants, interned objects, etc.
  1039. #
  1040. def close_global_decls(self):
  1041. # This is called when it is known that no more global declarations will
  1042. # declared.
  1043. self.generate_const_declarations()
  1044. if Options.cache_builtins:
  1045. w = self.parts['cached_builtins']
  1046. w.putln("return 0;")
  1047. if w.label_used(w.error_label):
  1048. w.put_label(w.error_label)
  1049. w.putln("return -1;")
  1050. w.putln("}")
  1051. w.exit_cfunc_scope()
  1052. w = self.parts['cached_constants']
  1053. w.put_finish_refcount_context()
  1054. w.putln("return 0;")
  1055. if w.label_used(w.error_label):
  1056. w.put_label(w.error_label)
  1057. w.put_finish_refcount_context()
  1058. w.putln("return -1;")
  1059. w.putln("}")
  1060. w.exit_cfunc_scope()
  1061. w = self.parts['init_globals']
  1062. w.putln("return 0;")
  1063. if w.label_used(w.error_label):
  1064. w.put_label(w.error_label)
  1065. w.putln("return -1;")
  1066. w.putln("}")
  1067. w.exit_cfunc_scope()
  1068. if Options.generate_cleanup_code:
  1069. w = self.parts['cleanup_globals']
  1070. w.putln("}")
  1071. w.exit_cfunc_scope()
  1072. if Options.generate_cleanup_code:
  1073. w = self.parts['cleanup_module']
  1074. w.putln("}")
  1075. w.exit_cfunc_scope()
  1076. def put_pyobject_decl(self, entry):
  1077. self['global_var'].putln("static PyObject *%s;" % entry.cname)
  1078. # constant handling at code generation time
  1079. def get_cached_constants_writer(self, target=None):
  1080. if target is not None:
  1081. if target in self.initialised_constants:
  1082. # Return None on second/later calls to prevent duplicate creation code.
  1083. return None
  1084. self.initialised_constants.add(target)
  1085. return self.parts['cached_constants']
  1086. def get_int_const(self, str_value, longness=False):
  1087. py_type = longness and 'long' or 'int'
  1088. try:
  1089. c = self.num_const_index[(str_value, py_type)]
  1090. except KeyError:
  1091. c = self.new_num_const(str_value, py_type)
  1092. return c
  1093. def get_float_const(self, str_value, value_code):
  1094. try:
  1095. c = self.num_const_index[(str_value, 'float')]
  1096. except KeyError:
  1097. c = self.new_num_const(str_value, 'float', value_code)
  1098. return c
  1099. def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None):
  1100. if dedup_key is not None:
  1101. const = self.dedup_const_index.get(dedup_key)
  1102. if const is not None:
  1103. return const
  1104. # create a new Python object constant
  1105. const = self.new_py_const(type, prefix)
  1106. if cleanup_level is not None \
  1107. and cleanup_level <= Options.generate_cleanup_code:
  1108. cleanup_writer = self.parts['cleanup_globals']
  1109. cleanup_writer.putln('Py_CLEAR(%s);' % const.cname)
  1110. if dedup_key is not None:
  1111. self.dedup_const_index[dedup_key] = const
  1112. return const
  1113. def get_string_const(self, text, py_version=None):
  1114. # return a C string constant, creating a new one if necessary
  1115. if text.is_unicode:
  1116. byte_string = text.utf8encode()
  1117. else:
  1118. byte_string = text.byteencode()
  1119. try:
  1120. c = self.string_const_index[byte_string]
  1121. except KeyError:
  1122. c = self.new_string_const(text, byte_string)
  1123. c.add_py_version(py_version)
  1124. return c
  1125. def get_pyunicode_ptr_const(self, text):
  1126. # return a Py_UNICODE[] constant, creating a new one if necessary
  1127. assert text.is_unicode
  1128. try:
  1129. c = self.pyunicode_ptr_const_index[text]
  1130. except KeyError:
  1131. c = self.pyunicode_ptr_const_index[text] = self.new_const_cname()
  1132. return c
  1133. def get_py_string_const(self, text, identifier=None,
  1134. is_str=False, unicode_value=None):
  1135. # return a Python string constant, creating a new one if necessary
  1136. py3str_cstring = None
  1137. if is_str and unicode_value is not None \
  1138. and unicode_value.utf8encode() != text.byteencode():
  1139. py3str_cstring = self.get_string_const(unicode_value, py_version=3)
  1140. c_string = self.get_string_const(text, py_version=2)
  1141. else:
  1142. c_string = self.get_string_const(text)
  1143. py_string = c_string.get_py_string_const(
  1144. text.encoding, identifier, is_str, py3str_cstring)
  1145. return py_string
  1146. def get_interned_identifier(self, text):
  1147. return self.get_py_string_const(text, identifier=True)
  1148. def new_string_const(self, text, byte_string):
  1149. cname = self.new_string_const_cname(byte_string)
  1150. c = StringConst(cname, text, byte_string)
  1151. self.string_const_index[byte_string] = c
  1152. return c
  1153. def new_num_const(self, value, py_type, value_code=None):
  1154. cname = self.new_num_const_cname(value, py_type)
  1155. c = NumConst(cname, value, py_type, value_code)
  1156. self.num_const_index[(value, py_type)] = c
  1157. return c
  1158. def new_py_const(self, type, prefix=''):
  1159. cname = self.new_const_cname(prefix)
  1160. c = PyObjectConst(cname, type)
  1161. self.py_constants.append(c)
  1162. return c
  1163. def new_string_const_cname(self, bytes_value):
  1164. # Create a new globally-unique nice name for a C string constant.
  1165. value = bytes_value.decode('ASCII', 'ignore')
  1166. return self.new_const_cname(value=value)
  1167. def new_num_const_cname(self, value, py_type):
  1168. if py_type == 'long':
  1169. value += 'L'
  1170. py_type = 'int'
  1171. prefix = Naming.interned_prefixes[py_type]
  1172. cname = "%s%s" % (prefix, value)
  1173. cname = cname.replace('+', '_').replace('-', 'neg_').replace('.', '_')
  1174. return cname
  1175. def new_const_cname(self, prefix='', value=''):
  1176. value = replace_identifier('_', value)[:32].strip('_')
  1177. used = self.const_cnames_used
  1178. name_suffix = value
  1179. while name_suffix in used:
  1180. counter = used[value] = used[value] + 1
  1181. name_suffix = '%s_%d' % (value, counter)
  1182. used[name_suffix] = 1
  1183. if prefix:
  1184. prefix = Naming.interned_prefixes[prefix]
  1185. else:
  1186. prefix = Naming.const_prefix
  1187. return "%s%s" % (prefix, name_suffix)
  1188. def get_cached_unbound_method(self, type_cname, method_name):
  1189. key = (type_cname, method_name)
  1190. try:
  1191. cname = self.cached_cmethods[key]
  1192. except KeyError:
  1193. cname = self.cached_cmethods[key] = self.new_const_cname(
  1194. 'umethod', '%s_%s' % (type_cname, method_name))
  1195. return cname
  1196. def cached_unbound_method_call_code(self, obj_cname, type_cname, method_name, arg_cnames):
  1197. # admittedly, not the best place to put this method, but it is reused by UtilityCode and ExprNodes ...
  1198. utility_code_name = "CallUnboundCMethod%d" % len(arg_cnames)
  1199. self.use_utility_code(UtilityCode.load_cached(utility_code_name, "ObjectHandling.c"))
  1200. cache_cname = self.get_cached_unbound_method(type_cname, method_name)
  1201. args = [obj_cname] + arg_cnames
  1202. return "__Pyx_%s(&%s, %s)" % (
  1203. utility_code_name,
  1204. cache_cname,
  1205. ', '.join(args),
  1206. )
  1207. def add_cached_builtin_decl(self, entry):
  1208. if entry.is_builtin and entry.is_const:
  1209. if self.should_declare(entry.cname, entry):
  1210. self.put_pyobject_decl(entry)
  1211. w = self.parts['cached_builtins']
  1212. condition = None
  1213. if entry.name in non_portable_builtins_map:
  1214. condition, replacement = non_portable_builtins_map[entry.name]
  1215. w.putln('#if %s' % condition)
  1216. self.put_cached_builtin_init(
  1217. entry.pos, StringEncoding.EncodedString(replacement),
  1218. entry.cname)
  1219. w.putln('#else')
  1220. self.put_cached_builtin_init(
  1221. entry.pos, StringEncoding.EncodedString(entry.name),
  1222. entry.cname)
  1223. if condition:
  1224. w.putln('#endif')
  1225. def put_cached_builtin_init(self, pos, name, cname):
  1226. w = self.parts['cached_builtins']
  1227. interned_cname = self.get_interned_identifier(name).cname
  1228. self.use_utility_code(
  1229. UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c"))
  1230. w.putln('%s = __Pyx_GetBuiltinName(%s); if (!%s) %s' % (
  1231. cname,
  1232. interned_cname,
  1233. cname,
  1234. w.error_goto(pos)))
  1235. def generate_const_declarations(self):
  1236. self.generate_cached_methods_decls()
  1237. self.generate_string_constants()
  1238. self.generate_num_constants()
  1239. self.generate_object_constant_decls()
  1240. def generate_object_constant_decls(self):
  1241. consts = [(len(c.cname), c.cname, c)
  1242. for c in self.py_constants]
  1243. consts.sort()
  1244. decls_writer = self.parts['decls']
  1245. for _, cname, c in consts:
  1246. decls_writer.putln(
  1247. "static %s;" % c.type.declaration_code(cname))
  1248. def generate_cached_methods_decls(self):
  1249. if not self.cached_cmethods:
  1250. return
  1251. decl = self.parts['decls']
  1252. init = self.parts['init_globals']
  1253. cnames = []
  1254. for (type_cname, method_name), cname in sorted(self.cached_cmethods.items()):
  1255. cnames.append(cname)
  1256. method_name_cname = self.get_interned_identifier(StringEncoding.EncodedString(method_name)).cname
  1257. decl.putln('static __Pyx_CachedCFunction %s = {0, &%s, 0, 0, 0};' % (
  1258. cname, method_name_cname))
  1259. # split type reference storage as it might not be static
  1260. init.putln('%s.type = (PyObject*)&%s;' % (
  1261. cname, type_cname))
  1262. if Options.generate_cleanup_code:
  1263. cleanup = self.parts['cleanup_globals']
  1264. for cname in cnames:
  1265. cleanup.putln("Py_CLEAR(%s.method);" % cname)
  1266. def generate_string_constants(self):
  1267. c_consts = [(len(c.cname), c.cname, c) for c in self.string_const_index.values()]
  1268. c_consts.sort()
  1269. py_strings = []
  1270. decls_writer = self.parts['string_decls']
  1271. for _, cname, c in c_consts:
  1272. conditional = False
  1273. if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
  1274. conditional = True
  1275. decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % (
  1276. (2 in c.py_versions) and '<' or '>='))
  1277. decls_writer.putln('static const char %s[] = "%s";' % (
  1278. cname, StringEncoding.split_string_literal(c.escaped_value)))
  1279. if conditional:
  1280. decls_writer.putln("#endif")
  1281. if c.py_strings is not None:
  1282. for py_string in c.py_strings.values():
  1283. py_strings.append((c.cname, len(py_string.cname), py_string))
  1284. for c, cname in sorted(self.pyunicode_ptr_const_index.items()):
  1285. utf16_array, utf32_array = StringEncoding.encode_pyunicode_string(c)
  1286. if utf16_array:
  1287. # Narrow and wide representations differ
  1288. decls_writer.putln("#ifdef Py_UNICODE_WIDE")
  1289. decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf32_array))
  1290. if utf16_array:
  1291. decls_writer.putln("#else")
  1292. decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf16_array))
  1293. decls_writer.putln("#endif")
  1294. if py_strings:
  1295. self.use_utility_code(UtilityCode.load_cached("InitStrings", "StringTools.c"))
  1296. py_strings.sort()
  1297. w = self.parts['pystring_table']
  1298. w.putln("")
  1299. w.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname)
  1300. for c_cname, _, py_string in py_strings:
  1301. if not py_string.is_str or not py_string.encoding or \
  1302. py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
  1303. 'UTF8', 'UTF-8'):
  1304. encoding = '0'
  1305. else:
  1306. encoding = '"%s"' % py_string.encoding.lower()
  1307. decls_writer.putln(
  1308. "static PyObject *%s;" % py_string.cname)
  1309. if py_string.py3str_cstring:
  1310. w.putln("#if PY_MAJOR_VERSION >= 3")
  1311. w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
  1312. py_string.cname,
  1313. py_string.py3str_cstring.cname,
  1314. py_string.py3str_cstring.cname,
  1315. '0', 1, 0,
  1316. py_string.intern
  1317. ))
  1318. w.putln("#else")
  1319. w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
  1320. py_string.cname,
  1321. c_cname,
  1322. c_cname,
  1323. encoding,
  1324. py_string.is_unicode,
  1325. py_string.is_str,
  1326. py_string.intern
  1327. ))
  1328. if py_string.py3str_cstring:
  1329. w.putln("#endif")
  1330. w.putln("{0, 0, 0, 0, 0, 0, 0}")
  1331. w.putln("};")
  1332. init_globals = self.parts['init_globals']
  1333. init_globals.putln(
  1334. "if (__Pyx_InitStrings(%s) < 0) %s;" % (
  1335. Naming.stringtab_cname,
  1336. init_globals.error_goto(self.module_pos)))
  1337. def generate_num_constants(self):
  1338. consts = [(c.py_type, c.value[0] == '-', len(c.value), c.value, c.value_code, c)
  1339. for c in self.num_const_index.values()]
  1340. consts.sort()
  1341. decls_writer = self.parts['decls']
  1342. init_globals = self.parts['init_globals']
  1343. for py_type, _, _, value, value_code, c in consts:
  1344. cname = c.cname
  1345. decls_writer.putln("static PyObject *%s;" % cname)
  1346. if py_type == 'float':
  1347. function = 'PyFloat_FromDouble(%s)'
  1348. elif py_type == 'long':
  1349. function = 'PyLong_FromString((char *)"%s", 0, 0)'
  1350. elif Utils.long_literal(value):
  1351. function = 'PyInt_FromString((char *)"%s", 0, 0)'
  1352. elif len(value.lstrip('-')) > 4:
  1353. function = "PyInt_FromLong(%sL)"
  1354. else:
  1355. function = "PyInt_FromLong(%s)"
  1356. init_globals.putln('%s = %s; %s' % (
  1357. cname, function % value_code,
  1358. init_globals.error_goto_if_null(cname, self.module_pos)))
  1359. # The functions below are there in a transition phase only
  1360. # and will be deprecated. They are called from Nodes.BlockNode.
  1361. # The copy&paste duplication is intentional in order to be able
  1362. # to see quickly how BlockNode worked, until this is replaced.
  1363. def should_declare(self, cname, entry):
  1364. if cname in self.declared_cnames:
  1365. other = self.declared_cnames[cname]
  1366. assert str(entry.type) == str(other.type)
  1367. assert entry.init == other.init
  1368. return False
  1369. else:
  1370. self.declared_cnames[cname] = entry
  1371. return True
  1372. #
  1373. # File name state
  1374. #
  1375. def lookup_filename(self, source_desc):
  1376. entry = source_desc.get_filenametable_entry()
  1377. try:
  1378. index = self.filename_table[entry]
  1379. except KeyError:
  1380. index = len(self.filename_list)
  1381. self.filename_list.append(source_desc)
  1382. self.filename_table[entry] = index
  1383. return index
  1384. def commented_file_contents(self, source_desc):
  1385. try:
  1386. return self.input_file_contents[source_desc]
  1387. except KeyError:
  1388. pass
  1389. source_file = source_desc.get_lines(encoding='ASCII',
  1390. error_handling='ignore')
  1391. try:
  1392. F = [u' * ' + line.rstrip().replace(
  1393. u'*/', u'*[inserted by cython to avoid comment closer]/'
  1394. ).replace(
  1395. u'/*', u'/[inserted by cython to avoid comment start]*'
  1396. )
  1397. for line in source_file]
  1398. finally:
  1399. if hasattr(source_file, 'close'):
  1400. source_file.close()
  1401. if not F: F.append(u'')
  1402. self.input_file_contents[source_desc] = F
  1403. return F
  1404. #
  1405. # Utility code state
  1406. #
  1407. def use_utility_code(self, utility_code):
  1408. """
  1409. Adds code to the C file. utility_code should
  1410. a) implement __eq__/__hash__ for the purpose of knowing whether the same
  1411. code has already been included
  1412. b) implement put_code, which takes a globalstate instance
  1413. See UtilityCode.
  1414. """
  1415. if utility_code and utility_code not in self.utility_codes:
  1416. self.utility_codes.add(utility_code)
  1417. utility_code.put_code(self)
  1418. def use_entry_utility_code(self, entry):
  1419. if entry is None:
  1420. return
  1421. if entry.utility_code:
  1422. self.use_utility_code(entry.utility_code)
  1423. if entry.utility_code_definition:
  1424. self.use_utility_code(entry.utility_code_definition)
  1425. def funccontext_property(func):
  1426. name = func.__name__
  1427. attribute_of = operator.attrgetter(name)
  1428. def get(self):
  1429. return attribute_of(self.funcstate)
  1430. def set(self, value):
  1431. setattr(self.funcstate, name, value)
  1432. return property(get, set)
  1433. class CCodeConfig(object):
  1434. # emit_linenums boolean write #line pragmas?
  1435. # emit_code_comments boolean copy the original code into C comments?
  1436. # c_line_in_traceback boolean append the c file and line number to the traceback for exceptions?
  1437. def __init__(self, emit_linenums=True, emit_code_comments=True, c_line_in_traceback=True):
  1438. self.emit_code_comments = emit_code_comments
  1439. self.emit_linenums = emit_linenums
  1440. self.c_line_in_traceback = c_line_in_traceback
  1441. class CCodeWriter(object):
  1442. """
  1443. Utility class to output C code.
  1444. When creating an insertion point one must care about the state that is
  1445. kept:
  1446. - formatting state (level, bol) is cloned and used in insertion points
  1447. as well
  1448. - labels, temps, exc_vars: One must construct a scope in which these can
  1449. exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
  1450. sanity checking and forward compatibility). Created insertion points
  1451. looses this scope and cannot access it.
  1452. - marker: Not copied to insertion point
  1453. - filename_table, filename_list, input_file_contents: All codewriters
  1454. coming from the same root share the same instances simultaneously.
  1455. """
  1456. # f file output file
  1457. # buffer StringIOTree
  1458. # level int indentation level
  1459. # bol bool beginning of line?
  1460. # marker string comment to emit before next line
  1461. # funcstate FunctionState contains state local to a C function used for code
  1462. # generation (labels and temps state etc.)
  1463. # globalstate GlobalState contains state global for a C file (input file info,
  1464. # utility code, declared constants etc.)
  1465. # pyclass_stack list used during recursive code generation to pass information
  1466. # about the current class one is in
  1467. # code_config CCodeConfig configuration options for the C code writer
  1468. @cython.locals(create_from='CCodeWriter')
  1469. def __init__(self, create_from=None, buffer=None, copy_formatting=False):
  1470. if buffer is None: buffer = StringIOTree()
  1471. self.buffer = buffer
  1472. self.last_pos = None
  1473. self.last_marked_pos = None
  1474. self.pyclass_stack = []
  1475. self.funcstate = None
  1476. self.globalstate = None
  1477. self.code_config = None
  1478. self.level = 0
  1479. self.call_level = 0
  1480. self.bol = 1
  1481. if create_from is not None:
  1482. # Use same global state
  1483. self.set_global_state(create_from.globalstate)
  1484. self.funcstate = create_from.funcstate
  1485. # Clone formatting state
  1486. if copy_formatting:
  1487. self.level = create_from.level
  1488. self.bol = create_from.bol
  1489. self.call_level = create_from.call_level
  1490. self.last_pos = create_from.last_pos
  1491. self.last_marked_pos = create_from.last_marked_pos
  1492. def create_new(self, create_from, buffer, copy_formatting):
  1493. # polymorphic constructor -- very slightly more versatile
  1494. # than using __class__
  1495. result = CCodeWriter(create_from, buffer, copy_formatting)
  1496. return result
  1497. def set_global_state(self, global_state):
  1498. assert self.globalstate is None # prevent overwriting once it's set
  1499. self.globalstate = global_state
  1500. self.code_config = global_state.code_config
  1501. def copyto(self, f):
  1502. self.buffer.copyto(f)
  1503. def getvalue(self):
  1504. return self.buffer.getvalue()
  1505. def write(self, s):
  1506. # also put invalid markers (lineno 0), to indicate that those lines
  1507. # have no Cython source code correspondence
  1508. cython_lineno = self.last_marked_pos[1] if self.last_marked_pos else 0
  1509. self.buffer.markers.extend([cython_lineno] * s.count('\n'))
  1510. self.buffer.write(s)
  1511. def insertion_point(self):
  1512. other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
  1513. return other
  1514. def new_writer(self):
  1515. """
  1516. Creates a new CCodeWriter connected to the same global state, which
  1517. can later be inserted using insert.
  1518. """
  1519. return CCodeWriter(create_from=self)
  1520. def insert(self, writer):
  1521. """
  1522. Inserts the contents of another code writer (created with
  1523. the same global state) in the current location.
  1524. It is ok to write to the inserted writer also after insertion.
  1525. """
  1526. assert writer.globalstate is self.globalstate
  1527. self.buffer.insert(writer.buffer)
  1528. # Properties delegated to function scope
  1529. @funccontext_property
  1530. def label_counter(self): pass
  1531. @funccontext_property
  1532. def return_label(self): pass
  1533. @funccontext_property
  1534. def error_label(self): pass
  1535. @funccontext_property
  1536. def labels_used(self): pass
  1537. @funccontext_property
  1538. def continue_label(self): pass
  1539. @funccontext_property
  1540. def break_label(self): pass
  1541. @funccontext_property
  1542. def return_from_error_cleanup_label(self): pass
  1543. @funccontext_property
  1544. def yield_labels(self): pass
  1545. # Functions delegated to function scope
  1546. def new_label(self, name=None): return self.funcstate.new_label(name)
  1547. def new_error_label(self): return self.funcstate.new_error_label()
  1548. def new_yield_label(self, *args): return self.funcstate.new_yield_label(*args)
  1549. def get_loop_labels(self): return self.funcstate.get_loop_labels()
  1550. def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
  1551. def new_loop_labels(self): return self.funcstate.new_loop_labels()
  1552. def get_all_labels(self): return self.funcstate.get_all_labels()
  1553. def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels)
  1554. def all_new_labels(self): return self.funcstate.all_new_labels()
  1555. def use_label(self, lbl): return self.funcstate.use_label(lbl)
  1556. def label_used(self, lbl): return self.funcstate.label_used(lbl)
  1557. def enter_cfunc_scope(self, scope=None):
  1558. self.funcstate = FunctionState(self, scope=scope)
  1559. def exit_cfunc_scope(self):
  1560. self.funcstate = None
  1561. # constant handling
  1562. def get_py_int(self, str_value, longness):
  1563. return self.globalstate.get_int_const(str_value, longness).cname
  1564. def get_py_float(self, str_value, value_code):
  1565. return self.globalstate.get_float_const(str_value, value_code).cname
  1566. def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None):
  1567. return self.globalstate.get_py_const(type, prefix, cleanup_level, dedup_key).cname
  1568. def get_string_const(self, text):
  1569. return self.globalstate.get_string_const(text).cname
  1570. def get_pyunicode_ptr_const(self, text):
  1571. return self.globalstate.get_pyunicode_ptr_const(text)
  1572. def get_py_string_const(self, text, identifier=None,
  1573. is_str=False, unicode_value=None):
  1574. return self.globalstate.get_py_string_const(
  1575. text, identifier, is_str, unicode_value).cname
  1576. def get_argument_default_const(self, type):
  1577. return self.globalstate.get_py_const(type).cname
  1578. def intern(self, text):
  1579. return self.get_py_string_const(text)
  1580. def intern_identifier(self, text):
  1581. return self.get_py_string_const(text, identifier=True)
  1582. def get_cached_constants_writer(self, target=None):
  1583. return self.globalstate.get_cached_constants_writer(target)
  1584. # code generation
  1585. def putln(self, code="", safe=False):
  1586. if self.last_pos and self.bol:
  1587. self.emit_marker()
  1588. if self.code_config.emit_linenums and self.last_marked_pos:
  1589. source_desc, line, _ = self.last_marked_pos
  1590. self.write('\n#line %s "%s"\n' % (line, source_desc.get_escaped_description()))
  1591. if code:
  1592. if safe:
  1593. self.put_safe(code)
  1594. else:
  1595. self.put(code)
  1596. self.write("\n")
  1597. self.bol = 1
  1598. def mark_pos(self, pos, trace=True):
  1599. if pos is None:
  1600. return
  1601. if self.last_marked_pos and self.last_marked_pos[:2] == pos[:2]:
  1602. return
  1603. self.last_pos = (pos, trace)
  1604. def emit_marker(self):
  1605. pos, trace = self.last_pos
  1606. self.last_marked_pos = pos
  1607. self.last_pos = None
  1608. self.write("\n")
  1609. if self.code_config.emit_code_comments:
  1610. self.indent()
  1611. self.write("/* %s */\n" % self._build_marker(pos))
  1612. if trace and self.funcstate and self.funcstate.can_trace and self.globalstate.directives['linetrace']:
  1613. self.indent()
  1614. self.write('__Pyx_TraceLine(%d,%d,%s)\n' % (
  1615. pos[1], not self.funcstate.gil_owned, self.error_goto(pos)))
  1616. def _build_marker(self, pos):
  1617. source_desc, line, col = pos
  1618. assert isinstance(source_desc, SourceDescriptor)
  1619. contents = self.globalstate.commented_file_contents(source_desc)
  1620. lines = contents[max(0, line-3):line] # line numbers start at 1
  1621. lines[-1] += u' # <<<<<<<<<<<<<<'
  1622. lines += contents[line:line+2]
  1623. return u'"%s":%d\n%s\n' % (source_desc.get_escaped_description(), line, u'\n'.join(lines))
  1624. def put_safe(self, code):
  1625. # put code, but ignore {}
  1626. self.write(code)
  1627. self.bol = 0
  1628. def put_or_include(self, code, name):
  1629. include_dir = self.globalstate.common_utility_include_dir
  1630. if include_dir and len(code) > 1024:
  1631. include_file = "%s_%s.h" % (
  1632. name, hashlib.md5(code.encode('utf8')).hexdigest())
  1633. path = os.path.join(include_dir, include_file)
  1634. if not os.path.exists(path):
  1635. tmp_path = '%s.tmp%s' % (path, os.getpid())
  1636. with closing(Utils.open_new_file(tmp_path)) as f:
  1637. f.write(code)
  1638. shutil.move(tmp_path, path)
  1639. code = '#include "%s"\n' % path
  1640. self.put(code)
  1641. def put(self, code):
  1642. fix_indent = False
  1643. if "{" in code:
  1644. dl = code.count("{")
  1645. else:
  1646. dl = 0
  1647. if "}" in code:
  1648. dl -= code.count("}")
  1649. if dl < 0:
  1650. self.level += dl
  1651. elif dl == 0 and code[0] == "}":
  1652. # special cases like "} else {" need a temporary dedent
  1653. fix_indent = True
  1654. self.level -= 1
  1655. if self.bol:
  1656. self.indent()
  1657. self.write(code)
  1658. self.bol = 0
  1659. if dl > 0:
  1660. self.level += dl
  1661. elif fix_indent:
  1662. self.level += 1
  1663. def putln_tempita(self, code, **context):
  1664. from ..Tempita import sub
  1665. self.putln(sub(code, **context))
  1666. def put_tempita(self, code, **context):
  1667. from ..Tempita import sub
  1668. self.put(sub(code, **context))
  1669. def increase_indent(self):
  1670. self.level += 1
  1671. def decrease_indent(self):
  1672. self.level -= 1
  1673. def begin_block(self):
  1674. self.putln("{")
  1675. self.increase_indent()
  1676. def end_block(self):
  1677. self.decrease_indent()
  1678. self.putln("}")
  1679. def indent(self):
  1680. self.write(" " * self.level)
  1681. def get_py_version_hex(self, pyversion):
  1682. return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
  1683. def put_label(self, lbl):
  1684. if lbl in self.funcstate.labels_used:
  1685. self.putln("%s:;" % lbl)
  1686. def put_goto(self, lbl):
  1687. self.funcstate.use_label(lbl)
  1688. self.putln("goto %s;" % lbl)
  1689. def put_var_declaration(self, entry, storage_class="",
  1690. dll_linkage=None, definition=True):
  1691. #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
  1692. if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
  1693. #print "...private and not definition, skipping", entry.cname ###
  1694. return
  1695. if entry.visibility == "private" and not entry.used:
  1696. #print "...private and not used, skipping", entry.cname ###
  1697. return
  1698. if storage_class:
  1699. self.put("%s " % storage_class)
  1700. if not entry.cf_used:
  1701. self.put('CYTHON_UNUSED ')
  1702. self.put(entry.type.declaration_code(
  1703. entry.cname, dll_linkage=dll_linkage))
  1704. if entry.init is not None:
  1705. self.put_safe(" = %s" % entry.type.literal_code(entry.init))
  1706. elif entry.type.is_pyobject:
  1707. self.put(" = NULL")
  1708. self.putln(";")
  1709. def put_temp_declarations(self, func_context):
  1710. for name, type, manage_ref, static in func_context.temps_allocated:
  1711. decl = type.declaration_code(name)
  1712. if type.is_pyobject:
  1713. self.putln("%s = NULL;" % decl)
  1714. elif type.is_memoryviewslice:
  1715. from . import MemoryView
  1716. self.putln("%s = %s;" % (decl, MemoryView.memslice_entry_init))
  1717. else:
  1718. self.putln("%s%s;" % (static and "static " or "", decl))
  1719. if func_context.should_declare_error_indicator:
  1720. if self.funcstate.uses_error_indicator:
  1721. unused = ''
  1722. else:
  1723. unused = 'CYTHON_UNUSED '
  1724. # Initialize these variables to silence compiler warnings
  1725. self.putln("%sint %s = 0;" % (unused, Naming.lineno_cname))
  1726. self.putln("%sconst char *%s = NULL;" % (unused, Naming.filename_cname))
  1727. self.putln("%sint %s = 0;" % (unused, Naming.clineno_cname))
  1728. def put_generated_by(self):
  1729. self.putln("/* Generated by Cython %s */" % Version.watermark)
  1730. self.putln("")
  1731. def put_h_guard(self, guard):
  1732. self.putln("#ifndef %s" % guard)
  1733. self.putln("#define %s" % guard)
  1734. def unlikely(self, cond):
  1735. if Options.gcc_branch_hints:
  1736. return 'unlikely(%s)' % cond
  1737. else:
  1738. return cond
  1739. def build_function_modifiers(self, modifiers, mapper=modifier_output_mapper):
  1740. if not modifiers:
  1741. return ''
  1742. return '%s ' % ' '.join([mapper(m,m) for m in modifiers])
  1743. # Python objects and reference counting
  1744. def entry_as_pyobject(self, entry):
  1745. type = entry.type
  1746. if (not entry.is_self_arg and not entry.type.is_complete()
  1747. or entry.type.is_extension_type):
  1748. return "(PyObject *)" + entry.cname
  1749. else:
  1750. return entry.cname
  1751. def as_pyobject(self, cname, type):
  1752. from .PyrexTypes import py_object_type, typecast
  1753. return typecast(py_object_type, type, cname)
  1754. def put_gotref(self, cname):
  1755. self.putln("__Pyx_GOTREF(%s);" % cname)
  1756. def put_giveref(self, cname):
  1757. self.putln("__Pyx_GIVEREF(%s);" % cname)
  1758. def put_xgiveref(self, cname):
  1759. self.putln("__Pyx_XGIVEREF(%s);" % cname)
  1760. def put_xgotref(self, cname):
  1761. self.putln("__Pyx_XGOTREF(%s);" % cname)
  1762. def put_incref(self, cname, type, nanny=True):
  1763. if nanny:
  1764. self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
  1765. else:
  1766. self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
  1767. def put_decref(self, cname, type, nanny=True):
  1768. self._put_decref(cname, type, nanny, null_check=False, clear=False)
  1769. def put_var_gotref(self, entry):
  1770. if entry.type.is_pyobject:
  1771. self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
  1772. def put_var_giveref(self, entry):
  1773. if entry.type.is_pyobject:
  1774. self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))
  1775. def put_var_xgotref(self, entry):
  1776. if entry.type.is_pyobject:
  1777. self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))
  1778. def put_var_xgiveref(self, entry):
  1779. if entry.type.is_pyobject:
  1780. self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
  1781. def put_var_incref(self, entry, nanny=True):
  1782. if entry.type.is_pyobject:
  1783. if nanny:
  1784. self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
  1785. else:
  1786. self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry))
  1787. def put_var_xincref(self, entry):
  1788. if entry.type.is_pyobject:
  1789. self.putln("__Pyx_XINCREF(%s);" % self.entry_as_pyobject(entry))
  1790. def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False):
  1791. self._put_decref(cname, type, nanny, null_check=False,
  1792. clear=True, clear_before_decref=clear_before_decref)
  1793. def put_xdecref(self, cname, type, nanny=True, have_gil=True):
  1794. self._put_decref(cname, type, nanny, null_check=True,
  1795. have_gil=have_gil, clear=False)
  1796. def put_xdecref_clear(self, cname, type, nanny=True, clear_before_decref=False):
  1797. self._put_decref(cname, type, nanny, null_check=True,
  1798. clear=True, clear_before_decref=clear_before_decref)
  1799. def _put_decref(self, cname, type, nanny=True, null_check=False,
  1800. have_gil=True, clear=False, clear_before_decref=False):
  1801. if type.is_memoryviewslice:
  1802. self.put_xdecref_memoryviewslice(cname, have_gil=have_gil)
  1803. return
  1804. prefix = '__Pyx' if nanny else 'Py'
  1805. X = 'X' if null_check else ''
  1806. if clear:
  1807. if clear_before_decref:
  1808. if not nanny:
  1809. X = '' # CPython doesn't have a Py_XCLEAR()
  1810. self.putln("%s_%sCLEAR(%s);" % (prefix, X, cname))
  1811. else:
  1812. self.putln("%s_%sDECREF(%s); %s = 0;" % (
  1813. prefix, X, self.as_pyobject(cname, type), cname))
  1814. else:
  1815. self.putln("%s_%sDECREF(%s);" % (
  1816. prefix, X, self.as_pyobject(cname, type)))
  1817. def put_decref_set(self, cname, rhs_cname):
  1818. self.putln("__Pyx_DECREF_SET(%s, %s);" % (cname, rhs_cname))
  1819. def put_xdecref_set(self, cname, rhs_cname):
  1820. self.putln("__Pyx_XDECREF_SET(%s, %s);" % (cname, rhs_cname))
  1821. def put_var_decref(self, entry):
  1822. if entry.type.is_pyobject:
  1823. self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
  1824. def put_var_xdecref(self, entry, nanny=True):
  1825. if entry.type.is_pyobject:
  1826. if nanny:
  1827. self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
  1828. else:
  1829. self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry))
  1830. def put_var_decref_clear(self, entry):
  1831. self._put_var_decref_clear(entry, null_check=False)
  1832. def put_var_xdecref_clear(self, entry):
  1833. self._put_var_decref_clear(entry, null_check=True)
  1834. def _put_var_decref_clear(self, entry, null_check):
  1835. if entry.type.is_pyobject:
  1836. if entry.in_closure:
  1837. # reset before DECREF to make sure closure state is
  1838. # consistent during call to DECREF()
  1839. self.putln("__Pyx_%sCLEAR(%s);" % (
  1840. null_check and 'X' or '',
  1841. entry.cname))
  1842. else:
  1843. self.putln("__Pyx_%sDECREF(%s); %s = 0;" % (
  1844. null_check and 'X' or '',
  1845. self.entry_as_pyobject(entry),
  1846. entry.cname))
  1847. def put_var_decrefs(self, entries, used_only = 0):
  1848. for entry in entries:
  1849. if not used_only or entry.used:
  1850. if entry.xdecref_cleanup:
  1851. self.put_var_xdecref(entry)
  1852. else:
  1853. self.put_var_decref(entry)
  1854. def put_var_xdecrefs(self, entries):
  1855. for entry in entries:
  1856. self.put_var_xdecref(entry)
  1857. def put_var_xdecrefs_clear(self, entries):
  1858. for entry in entries:
  1859. self.put_var_xdecref_clear(entry)
  1860. def put_incref_memoryviewslice(self, slice_cname, have_gil=False):
  1861. from . import MemoryView
  1862. self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
  1863. self.putln("__PYX_INC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
  1864. def put_xdecref_memoryviewslice(self, slice_cname, have_gil=False):
  1865. from . import MemoryView
  1866. self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
  1867. self.putln("__PYX_XDEC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
  1868. def put_xgiveref_memoryviewslice(self, slice_cname):
  1869. self.put_xgiveref("%s.memview" % slice_cname)
  1870. def put_init_to_py_none(self, cname, type, nanny=True):
  1871. from .PyrexTypes import py_object_type, typecast
  1872. py_none = typecast(type, py_object_type, "Py_None")
  1873. if nanny:
  1874. self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
  1875. else:
  1876. self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
  1877. def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
  1878. code = template % entry.cname
  1879. #if entry.type.is_extension_type:
  1880. # code = "((PyObject*)%s)" % code
  1881. self.put_init_to_py_none(code, entry.type, nanny)
  1882. if entry.in_closure:
  1883. self.put_giveref('Py_None')
  1884. def put_pymethoddef(self, entry, term, allow_skip=True, wrapper_code_writer=None):
  1885. if entry.is_special or entry.name == '__getattribute__':
  1886. if entry.name not in special_py_methods:
  1887. if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
  1888. pass
  1889. # Python's typeobject.c will automatically fill in our slot
  1890. # in add_operators() (called by PyType_Ready) with a value
  1891. # that's better than ours.
  1892. elif allow_skip:
  1893. return
  1894. method_flags = entry.signature.method_flags()
  1895. if not method_flags:
  1896. return
  1897. if entry.is_special:
  1898. from . import TypeSlots
  1899. method_flags += [TypeSlots.method_coexist]
  1900. func_ptr = wrapper_code_writer.put_pymethoddef_wrapper(entry) if wrapper_code_writer else entry.func_cname
  1901. # Add required casts, but try not to shadow real warnings.
  1902. cast = '__Pyx_PyCFunctionFast' if 'METH_FASTCALL' in method_flags else 'PyCFunction'
  1903. if 'METH_KEYWORDS' in method_flags:
  1904. cast += 'WithKeywords'
  1905. if cast != 'PyCFunction':
  1906. func_ptr = '(void*)(%s)%s' % (cast, func_ptr)
  1907. self.putln(
  1908. '{"%s", (PyCFunction)%s, %s, %s}%s' % (
  1909. entry.name,
  1910. func_ptr,
  1911. "|".join(method_flags),
  1912. entry.doc_cname if entry.doc else '0',
  1913. term))
  1914. def put_pymethoddef_wrapper(self, entry):
  1915. func_cname = entry.func_cname
  1916. if entry.is_special:
  1917. method_flags = entry.signature.method_flags()
  1918. if method_flags and 'METH_NOARGS' in method_flags:
  1919. # Special NOARGS methods really take no arguments besides 'self', but PyCFunction expects one.
  1920. func_cname = Naming.method_wrapper_prefix + func_cname
  1921. self.putln("static PyObject *%s(PyObject *self, CYTHON_UNUSED PyObject *arg) {return %s(self);}" % (
  1922. func_cname, entry.func_cname))
  1923. return func_cname
  1924. # GIL methods
  1925. def put_ensure_gil(self, declare_gilstate=True, variable=None):
  1926. """
  1927. Acquire the GIL. The generated code is safe even when no PyThreadState
  1928. has been allocated for this thread (for threads not initialized by
  1929. using the Python API). Additionally, the code generated by this method
  1930. may be called recursively.
  1931. """
  1932. self.globalstate.use_utility_code(
  1933. UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
  1934. if self.globalstate.directives['fast_gil']:
  1935. self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
  1936. else:
  1937. self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
  1938. self.putln("#ifdef WITH_THREAD")
  1939. if not variable:
  1940. variable = '__pyx_gilstate_save'
  1941. if declare_gilstate:
  1942. self.put("PyGILState_STATE ")
  1943. self.putln("%s = __Pyx_PyGILState_Ensure();" % variable)
  1944. self.putln("#endif")
  1945. def put_release_ensured_gil(self, variable=None):
  1946. """
  1947. Releases the GIL, corresponds to `put_ensure_gil`.
  1948. """
  1949. if self.globalstate.directives['fast_gil']:
  1950. self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
  1951. else:
  1952. self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
  1953. if not variable:
  1954. variable = '__pyx_gilstate_save'
  1955. self.putln("#ifdef WITH_THREAD")
  1956. self.putln("__Pyx_PyGILState_Release(%s);" % variable)
  1957. self.putln("#endif")
  1958. def put_acquire_gil(self, variable=None):
  1959. """
  1960. Acquire the GIL. The thread's thread state must have been initialized
  1961. by a previous `put_release_gil`
  1962. """
  1963. if self.globalstate.directives['fast_gil']:
  1964. self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
  1965. else:
  1966. self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
  1967. self.putln("#ifdef WITH_THREAD")
  1968. self.putln("__Pyx_FastGIL_Forget();")
  1969. if variable:
  1970. self.putln('_save = %s;' % variable)
  1971. self.putln("Py_BLOCK_THREADS")
  1972. self.putln("#endif")
  1973. def put_release_gil(self, variable=None):
  1974. "Release the GIL, corresponds to `put_acquire_gil`."
  1975. if self.globalstate.directives['fast_gil']:
  1976. self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
  1977. else:
  1978. self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
  1979. self.putln("#ifdef WITH_THREAD")
  1980. self.putln("PyThreadState *_save;")
  1981. self.putln("Py_UNBLOCK_THREADS")
  1982. if variable:
  1983. self.putln('%s = _save;' % variable)
  1984. self.putln("__Pyx_FastGIL_Remember();")
  1985. self.putln("#endif")
  1986. def declare_gilstate(self):
  1987. self.putln("#ifdef WITH_THREAD")
  1988. self.putln("PyGILState_STATE __pyx_gilstate_save;")
  1989. self.putln("#endif")
  1990. # error handling
  1991. def put_error_if_neg(self, pos, value):
  1992. # TODO this path is almost _never_ taken, yet this macro makes is slower!
  1993. # return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos)))
  1994. return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
  1995. def put_error_if_unbound(self, pos, entry, in_nogil_context=False):
  1996. from . import ExprNodes
  1997. if entry.from_closure:
  1998. func = '__Pyx_RaiseClosureNameError'
  1999. self.globalstate.use_utility_code(
  2000. ExprNodes.raise_closure_name_error_utility_code)
  2001. elif entry.type.is_memoryviewslice and in_nogil_context:
  2002. func = '__Pyx_RaiseUnboundMemoryviewSliceNogil'
  2003. self.globalstate.use_utility_code(
  2004. ExprNodes.raise_unbound_memoryview_utility_code_nogil)
  2005. else:
  2006. func = '__Pyx_RaiseUnboundLocalError'
  2007. self.globalstate.use_utility_code(
  2008. ExprNodes.raise_unbound_local_error_utility_code)
  2009. self.putln('if (unlikely(!%s)) { %s("%s"); %s }' % (
  2010. entry.type.check_for_null_code(entry.cname),
  2011. func,
  2012. entry.name,
  2013. self.error_goto(pos)))
  2014. def set_error_info(self, pos, used=False):
  2015. self.funcstate.should_declare_error_indicator = True
  2016. if used:
  2017. self.funcstate.uses_error_indicator = True
  2018. return "__PYX_MARK_ERR_POS(%s, %s)" % (
  2019. self.lookup_filename(pos[0]),
  2020. pos[1])
  2021. def error_goto(self, pos, used=True):
  2022. lbl = self.funcstate.error_label
  2023. self.funcstate.use_label(lbl)
  2024. if pos is None:
  2025. return 'goto %s;' % lbl
  2026. self.funcstate.should_declare_error_indicator = True
  2027. if used:
  2028. self.funcstate.uses_error_indicator = True
  2029. return "__PYX_ERR(%s, %s, %s)" % (
  2030. self.lookup_filename(pos[0]),
  2031. pos[1],
  2032. lbl)
  2033. def error_goto_if(self, cond, pos):
  2034. return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
  2035. def error_goto_if_null(self, cname, pos):
  2036. return self.error_goto_if("!%s" % cname, pos)
  2037. def error_goto_if_neg(self, cname, pos):
  2038. return self.error_goto_if("%s < 0" % cname, pos)
  2039. def error_goto_if_PyErr(self, pos):
  2040. return self.error_goto_if("PyErr_Occurred()", pos)
  2041. def lookup_filename(self, filename):
  2042. return self.globalstate.lookup_filename(filename)
  2043. def put_declare_refcount_context(self):
  2044. self.putln('__Pyx_RefNannyDeclarations')
  2045. def put_setup_refcount_context(self, name, acquire_gil=False):
  2046. if acquire_gil:
  2047. self.globalstate.use_utility_code(
  2048. UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
  2049. self.putln('__Pyx_RefNannySetupContext("%s", %d);' % (name, acquire_gil and 1 or 0))
  2050. def put_finish_refcount_context(self):
  2051. self.putln("__Pyx_RefNannyFinishContext();")
  2052. def put_add_traceback(self, qualified_name, include_cline=True):
  2053. """
  2054. Build a Python traceback for propagating exceptions.
  2055. qualified_name should be the qualified name of the function.
  2056. """
  2057. format_tuple = (
  2058. qualified_name,
  2059. Naming.clineno_cname if include_cline else 0,
  2060. Naming.lineno_cname,
  2061. Naming.filename_cname,
  2062. )
  2063. self.funcstate.uses_error_indicator = True
  2064. self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple)
  2065. def put_unraisable(self, qualified_name, nogil=False):
  2066. """
  2067. Generate code to print a Python warning for an unraisable exception.
  2068. qualified_name should be the qualified name of the function.
  2069. """
  2070. format_tuple = (
  2071. qualified_name,
  2072. Naming.clineno_cname,
  2073. Naming.lineno_cname,
  2074. Naming.filename_cname,
  2075. self.globalstate.directives['unraisable_tracebacks'],
  2076. nogil,
  2077. )
  2078. self.funcstate.uses_error_indicator = True
  2079. self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %d, %d);' % format_tuple)
  2080. self.globalstate.use_utility_code(
  2081. UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
  2082. def put_trace_declarations(self):
  2083. self.putln('__Pyx_TraceDeclarations')
  2084. def put_trace_frame_init(self, codeobj=None):
  2085. if codeobj:
  2086. self.putln('__Pyx_TraceFrameInit(%s)' % codeobj)
  2087. def put_trace_call(self, name, pos, nogil=False):
  2088. self.putln('__Pyx_TraceCall("%s", %s[%s], %s, %d, %s);' % (
  2089. name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1], nogil, self.error_goto(pos)))
  2090. def put_trace_exception(self):
  2091. self.putln("__Pyx_TraceException();")
  2092. def put_trace_return(self, retvalue_cname, nogil=False):
  2093. self.putln("__Pyx_TraceReturn(%s, %d);" % (retvalue_cname, nogil))
  2094. def putln_openmp(self, string):
  2095. self.putln("#ifdef _OPENMP")
  2096. self.putln(string)
  2097. self.putln("#endif /* _OPENMP */")
  2098. def undef_builtin_expect(self, cond):
  2099. """
  2100. Redefine the macros likely() and unlikely to no-ops, depending on
  2101. condition 'cond'
  2102. """
  2103. self.putln("#if %s" % cond)
  2104. self.putln(" #undef likely")
  2105. self.putln(" #undef unlikely")
  2106. self.putln(" #define likely(x) (x)")
  2107. self.putln(" #define unlikely(x) (x)")
  2108. self.putln("#endif")
  2109. def redef_builtin_expect(self, cond):
  2110. self.putln("#if %s" % cond)
  2111. self.putln(" #undef likely")
  2112. self.putln(" #undef unlikely")
  2113. self.putln(" #define likely(x) __builtin_expect(!!(x), 1)")
  2114. self.putln(" #define unlikely(x) __builtin_expect(!!(x), 0)")
  2115. self.putln("#endif")
  2116. class PyrexCodeWriter(object):
  2117. # f file output file
  2118. # level int indentation level
  2119. def __init__(self, outfile_name):
  2120. self.f = Utils.open_new_file(outfile_name)
  2121. self.level = 0
  2122. def putln(self, code):
  2123. self.f.write("%s%s\n" % (" " * self.level, code))
  2124. def indent(self):
  2125. self.level += 1
  2126. def dedent(self):
  2127. self.level -= 1
  2128. class PyxCodeWriter(object):
  2129. """
  2130. Can be used for writing out some Cython code. To use the indenter
  2131. functionality, the Cython.Compiler.Importer module will have to be used
  2132. to load the code to support python 2.4
  2133. """
  2134. def __init__(self, buffer=None, indent_level=0, context=None, encoding='ascii'):
  2135. self.buffer = buffer or StringIOTree()
  2136. self.level = indent_level
  2137. self.context = context
  2138. self.encoding = encoding
  2139. def indent(self, levels=1):
  2140. self.level += levels
  2141. return True
  2142. def dedent(self, levels=1):
  2143. self.level -= levels
  2144. def indenter(self, line):
  2145. """
  2146. Instead of
  2147. with pyx_code.indenter("for i in range(10):"):
  2148. pyx_code.putln("print i")
  2149. write
  2150. if pyx_code.indenter("for i in range(10);"):
  2151. pyx_code.putln("print i")
  2152. pyx_code.dedent()
  2153. """
  2154. self.putln(line)
  2155. self.indent()
  2156. return True
  2157. def getvalue(self):
  2158. result = self.buffer.getvalue()
  2159. if isinstance(result, bytes):
  2160. result = result.decode(self.encoding)
  2161. return result
  2162. def putln(self, line, context=None):
  2163. context = context or self.context
  2164. if context:
  2165. line = sub_tempita(line, context)
  2166. self._putln(line)
  2167. def _putln(self, line):
  2168. self.buffer.write("%s%s\n" % (self.level * " ", line))
  2169. def put_chunk(self, chunk, context=None):
  2170. context = context or self.context
  2171. if context:
  2172. chunk = sub_tempita(chunk, context)
  2173. chunk = textwrap.dedent(chunk)
  2174. for line in chunk.splitlines():
  2175. self._putln(line)
  2176. def insertion_point(self):
  2177. return PyxCodeWriter(self.buffer.insertion_point(), self.level,
  2178. self.context)
  2179. def named_insertion_point(self, name):
  2180. setattr(self, name, self.insertion_point())
  2181. class ClosureTempAllocator(object):
  2182. def __init__(self, klass):
  2183. self.klass = klass
  2184. self.temps_allocated = {}
  2185. self.temps_free = {}
  2186. self.temps_count = 0
  2187. def reset(self):
  2188. for type, cnames in self.temps_allocated.items():
  2189. self.temps_free[type] = list(cnames)
  2190. def allocate_temp(self, type):
  2191. if type not in self.temps_allocated:
  2192. self.temps_allocated[type] = []
  2193. self.temps_free[type] = []
  2194. elif self.temps_free[type]:
  2195. return self.temps_free[type].pop(0)
  2196. cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
  2197. self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
  2198. self.temps_allocated[type].append(cname)
  2199. self.temps_count += 1
  2200. return cname