Code.py 95 KB

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