Cython has moved to github.

cython-devel

view Cython/Compiler/Nodes.py @ 3091:1a2e04bc1395

remove dependency on structmember.h
author Lisandro Dalcin <dalcinl@gmail.com>
date Thu Mar 11 17:21:13 2010 -0300 (2 years ago)
parents f31d1fa91d44
children 667c147a8dc2
line source
2 #
3 # Pyrex - Parse tree nodes
4 #
6 import sys, os, time, copy
8 try:
9 set
10 except NameError:
11 # Python 2.3
12 from sets import Set as set
14 import Code
15 import Builtin
16 from Errors import error, warning, InternalError
17 import Naming
18 import PyrexTypes
19 import TypeSlots
20 from PyrexTypes import py_object_type, error_type, CFuncType
21 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
22 StructOrUnionScope, PyClassScope, CClassScope, CppClassScope
23 from Cython.Utils import open_new_file, replace_suffix
24 from Code import UtilityCode
25 from StringEncoding import EncodedString, escape_byte_string, split_string_literal
26 import Options
27 import ControlFlow
28 import DebugFlags
30 absolute_path_length = 0
32 def relative_position(pos):
33 """
34 We embed the relative filename in the generated C file, since we
35 don't want to have to regnerate and compile all the source code
36 whenever the Python install directory moves (which could happen,
37 e.g,. when distributing binaries.)
39 INPUT:
40 a position tuple -- (absolute filename, line number column position)
42 OUTPUT:
43 relative filename
44 line number
46 AUTHOR: William Stein
47 """
48 global absolute_path_length
49 if absolute_path_length==0:
50 absolute_path_length = len(os.path.abspath(os.getcwd()))
51 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
53 def embed_position(pos, docstring):
54 if not Options.embed_pos_in_docstring:
55 return docstring
56 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
57 if docstring is None:
58 # unicode string
59 return EncodedString(pos_line)
61 # make sure we can encode the filename in the docstring encoding
62 # otherwise make the docstring a unicode string
63 encoding = docstring.encoding
64 if encoding is not None:
65 try:
66 encoded_bytes = pos_line.encode(encoding)
67 except UnicodeEncodeError:
68 encoding = None
70 if not docstring:
71 # reuse the string encoding of the original docstring
72 doc = EncodedString(pos_line)
73 else:
74 doc = EncodedString(pos_line + u'\n' + docstring)
75 doc.encoding = encoding
76 return doc
79 from Code import CCodeWriter
80 from types import FunctionType
82 def write_func_call(func):
83 def f(*args, **kwds):
84 if len(args) > 1 and isinstance(args[1], CCodeWriter):
85 # here we annotate the code with this function call
86 # but only if new code is generated
87 node, code = args[:2]
88 marker = ' /* %s -> %s.%s %s */' % (
89 ' ' * code.call_level,
90 node.__class__.__name__,
91 func.__name__,
92 node.pos[1:])
93 pristine = code.buffer.stream.tell()
94 code.putln(marker)
95 start = code.buffer.stream.tell()
96 code.call_level += 4
97 res = func(*args, **kwds)
98 code.call_level -= 4
99 if start == code.buffer.stream.tell():
100 code.buffer.stream.seek(pristine)
101 else:
102 marker = marker.replace('->', '<-')
103 code.putln(marker)
104 return res
105 else:
106 return func(*args, **kwds)
107 return f
109 class VerboseCodeWriter(type):
110 # Set this as a metaclass to trace function calls in code.
111 # This slows down code generation and makes much larger files.
112 def __new__(cls, name, bases, attrs):
113 attrs = dict(attrs)
114 for mname, m in attrs.items():
115 if isinstance(m, FunctionType):
116 attrs[mname] = write_func_call(m)
117 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
120 class Node(object):
121 # pos (string, int, int) Source file position
122 # is_name boolean Is a NameNode
123 # is_literal boolean Is a ConstNode
125 if DebugFlags.debug_trace_code_generation:
126 __metaclass__ = VerboseCodeWriter
128 is_name = 0
129 is_literal = 0
130 temps = None
132 # All descandants should set child_attrs to a list of the attributes
133 # containing nodes considered "children" in the tree. Each such attribute
134 # can either contain a single node or a list of nodes. See Visitor.py.
135 child_attrs = None
137 def __init__(self, pos, **kw):
138 self.pos = pos
139 self.__dict__.update(kw)
141 gil_message = "Operation"
143 nogil_check = None
145 def gil_error(self, env=None):
146 error(self.pos, "%s not allowed without gil" % self.gil_message)
148 cpp_message = "Operation"
150 def cpp_check(self, env):
151 if not env.is_cpp():
152 self.cpp_error()
154 def cpp_error(self):
155 error(self.pos, "%s only allowed in c++" % self.cpp_message)
157 def clone_node(self):
158 """Clone the node. This is defined as a shallow copy, except for member lists
159 amongst the child attributes (from get_child_accessors) which are also
160 copied. Lists containing child nodes are thus seen as a way for the node
161 to hold multiple children directly; the list is not treated as a seperate
162 level in the tree."""
163 result = copy.copy(self)
164 for attrname in result.child_attrs:
165 value = getattr(result, attrname)
166 if isinstance(value, list):
167 setattr(result, attrname, [x for x in value])
168 return result
171 #
172 # There are 4 phases of parse tree processing, applied in order to
173 # all the statements in a given scope-block:
174 #
175 # (0) analyse_control_flow
176 # Create the control flow tree into which state can be asserted and
177 # queried.
178 #
179 # (1) analyse_declarations
180 # Make symbol table entries for all declarations at the current
181 # level, both explicit (def, cdef, etc.) and implicit (assignment
182 # to an otherwise undeclared name).
183 #
184 # (2) analyse_expressions
185 # Determine the result types of expressions and fill in the
186 # 'type' attribute of each ExprNode. Insert coercion nodes into the
187 # tree where needed to convert to and from Python objects.
188 # Allocate temporary locals for intermediate results. Fill
189 # in the 'result_code' attribute of each ExprNode with a C code
190 # fragment.
191 #
192 # (3) generate_code
193 # Emit C code for all declarations, statements and expressions.
194 # Recursively applies the 3 processing phases to the bodies of
195 # functions.
196 #
198 def analyse_control_flow(self, env):
199 pass
201 def analyse_declarations(self, env):
202 pass
204 def analyse_expressions(self, env):
205 raise InternalError("analyse_expressions not implemented for %s" % \
206 self.__class__.__name__)
208 def generate_code(self, code):
209 raise InternalError("generate_code not implemented for %s" % \
210 self.__class__.__name__)
212 def annotate(self, code):
213 # mro does the wrong thing
214 if isinstance(self, BlockNode):
215 self.body.annotate(code)
217 def end_pos(self):
218 try:
219 return self._end_pos
220 except AttributeError:
221 pos = self.pos
222 if not self.child_attrs:
223 self._end_pos = pos
224 return pos
225 for attr in self.child_attrs:
226 child = getattr(self, attr)
227 # Sometimes lists, sometimes nodes
228 if child is None:
229 pass
230 elif isinstance(child, list):
231 for c in child:
232 pos = max(pos, c.end_pos())
233 else:
234 pos = max(pos, child.end_pos())
235 self._end_pos = pos
236 return pos
238 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
239 if cutoff == 0:
240 return "<...nesting level cutoff...>"
241 if encountered is None:
242 encountered = set()
243 if id(self) in encountered:
244 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
245 encountered.add(id(self))
247 def dump_child(x, level):
248 if isinstance(x, Node):
249 return x.dump(level, filter_out, cutoff-1, encountered)
250 elif isinstance(x, list):
251 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
252 else:
253 return repr(x)
256 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
257 if len(attrs) == 0:
258 return "<%s (%d)>" % (self.__class__.__name__, id(self))
259 else:
260 indent = " " * level
261 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
262 for key, value in attrs:
263 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
264 res += "%s>" % indent
265 return res
267 class CompilerDirectivesNode(Node):
268 """
269 Sets compiler directives for the children nodes
270 """
271 # directives {string:value} A dictionary holding the right value for
272 # *all* possible directives.
273 # body Node
274 child_attrs = ["body"]
276 def analyse_control_flow(self, env):
277 old = env.directives
278 env.directives = self.directives
279 self.body.analyse_control_flow(env)
280 env.directives = old
282 def analyse_declarations(self, env):
283 old = env.directives
284 env.directives = self.directives
285 self.body.analyse_declarations(env)
286 env.directives = old
288 def analyse_expressions(self, env):
289 old = env.directives
290 env.directives = self.directives
291 self.body.analyse_expressions(env)
292 env.directives = old
294 def generate_function_definitions(self, env, code):
295 env_old = env.directives
296 code_old = code.globalstate.directives
297 code.globalstate.directives = self.directives
298 self.body.generate_function_definitions(env, code)
299 env.directives = env_old
300 code.globalstate.directives = code_old
302 def generate_execution_code(self, code):
303 old = code.globalstate.directives
304 code.globalstate.directives = self.directives
305 self.body.generate_execution_code(code)
306 code.globalstate.directives = old
308 def annotate(self, code):
309 old = code.globalstate.directives
310 code.globalstate.directives = self.directives
311 self.body.annotate(code)
312 code.globalstate.directives = old
314 class BlockNode(object):
315 # Mixin class for nodes representing a declaration block.
317 def generate_cached_builtins_decls(self, env, code):
318 entries = env.global_scope().undeclared_cached_builtins
319 for entry in entries:
320 code.globalstate.add_cached_builtin_decl(entry)
321 del entries[:]
324 class StatListNode(Node):
325 # stats a list of StatNode
327 child_attrs = ["stats"]
329 def create_analysed(pos, env, *args, **kw):
330 node = StatListNode(pos, *args, **kw)
331 return node # No node-specific analysis necesarry
332 create_analysed = staticmethod(create_analysed)
334 def analyse_control_flow(self, env):
335 for stat in self.stats:
336 stat.analyse_control_flow(env)
338 def analyse_declarations(self, env):
339 #print "StatListNode.analyse_declarations" ###
340 for stat in self.stats:
341 stat.analyse_declarations(env)
343 def analyse_expressions(self, env):
344 #print "StatListNode.analyse_expressions" ###
345 for stat in self.stats:
346 stat.analyse_expressions(env)
348 def generate_function_definitions(self, env, code):
349 #print "StatListNode.generate_function_definitions" ###
350 for stat in self.stats:
351 stat.generate_function_definitions(env, code)
353 def generate_execution_code(self, code):
354 #print "StatListNode.generate_execution_code" ###
355 for stat in self.stats:
356 code.mark_pos(stat.pos)
357 stat.generate_execution_code(code)
359 def annotate(self, code):
360 for stat in self.stats:
361 stat.annotate(code)
364 class StatNode(Node):
365 #
366 # Code generation for statements is split into the following subphases:
367 #
368 # (1) generate_function_definitions
369 # Emit C code for the definitions of any structs,
370 # unions, enums and functions defined in the current
371 # scope-block.
372 #
373 # (2) generate_execution_code
374 # Emit C code for executable statements.
375 #
377 def generate_function_definitions(self, env, code):
378 pass
380 def generate_execution_code(self, code):
381 raise InternalError("generate_execution_code not implemented for %s" % \
382 self.__class__.__name__)
385 class CDefExternNode(StatNode):
386 # include_file string or None
387 # body StatNode
389 child_attrs = ["body"]
391 def analyse_declarations(self, env):
392 if self.include_file:
393 env.add_include_file(self.include_file)
394 old_cinclude_flag = env.in_cinclude
395 env.in_cinclude = 1
396 self.body.analyse_declarations(env)
397 env.in_cinclude = old_cinclude_flag
399 def analyse_expressions(self, env):
400 pass
402 def generate_execution_code(self, code):
403 pass
405 def annotate(self, code):
406 self.body.annotate(code)
409 class CDeclaratorNode(Node):
410 # Part of a C declaration.
411 #
412 # Processing during analyse_declarations phase:
413 #
414 # analyse
415 # Returns (name, type) pair where name is the
416 # CNameDeclaratorNode of the name being declared
417 # and type is the type it is being declared as.
418 #
419 # calling_convention string Calling convention of CFuncDeclaratorNode
420 # for which this is a base
422 child_attrs = []
424 calling_convention = ""
427 class CNameDeclaratorNode(CDeclaratorNode):
428 # name string The Pyrex name being declared
429 # cname string or None C name, if specified
430 # default ExprNode or None the value assigned on declaration
432 child_attrs = ['default']
434 default = None
436 def analyse(self, base_type, env, nonempty = 0):
437 if nonempty and self.name == '':
438 # May have mistaken the name for the type.
439 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
440 error(self.pos, "Missing argument name")
441 elif base_type.is_void:
442 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
443 else:
444 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
445 base_type = py_object_type
446 self.type = base_type
447 return self, base_type
449 class CPtrDeclaratorNode(CDeclaratorNode):
450 # base CDeclaratorNode
452 child_attrs = ["base"]
454 def analyse(self, base_type, env, nonempty = 0):
455 if base_type.is_pyobject:
456 error(self.pos,
457 "Pointer base type cannot be a Python object")
458 ptr_type = PyrexTypes.c_ptr_type(base_type)
459 return self.base.analyse(ptr_type, env, nonempty = nonempty)
461 class CReferenceDeclaratorNode(CDeclaratorNode):
462 # base CDeclaratorNode
464 child_attrs = ["base"]
466 def analyse(self, base_type, env, nonempty = 0):
467 if base_type.is_pyobject:
468 error(self.pos,
469 "Reference base type cannot be a Python object")
470 ref_type = PyrexTypes.c_ref_type(base_type)
471 return self.base.analyse(ref_type, env, nonempty = nonempty)
473 class CArrayDeclaratorNode(CDeclaratorNode):
474 # base CDeclaratorNode
475 # dimension ExprNode
477 child_attrs = ["base", "dimension"]
479 def analyse(self, base_type, env, nonempty = 0):
480 if base_type.is_cpp_class:
481 from ExprNodes import TupleNode
482 if isinstance(self.dimension, TupleNode):
483 args = self.dimension.args
484 else:
485 args = self.dimension,
486 values = [v.analyse_as_type(env) for v in args]
487 if None in values:
488 ix = values.index(None)
489 error(args[ix].pos, "Template parameter not a type.")
490 return error_type
491 base_type = base_type.specialize_here(self.pos, values)
492 return self.base.analyse(base_type, env, nonempty = nonempty)
493 if self.dimension:
494 self.dimension.analyse_const_expression(env)
495 if not self.dimension.type.is_int:
496 error(self.dimension.pos, "Array dimension not integer")
497 size = self.dimension.get_constant_c_result_code()
498 if size is not None:
499 try:
500 size = int(size)
501 except ValueError:
502 # runtime constant?
503 pass
504 else:
505 size = None
506 if not base_type.is_complete():
507 error(self.pos,
508 "Array element type '%s' is incomplete" % base_type)
509 if base_type.is_pyobject:
510 error(self.pos,
511 "Array element cannot be a Python object")
512 if base_type.is_cfunction:
513 error(self.pos,
514 "Array element cannot be a function")
515 array_type = PyrexTypes.c_array_type(base_type, size)
516 return self.base.analyse(array_type, env, nonempty = nonempty)
519 class CFuncDeclaratorNode(CDeclaratorNode):
520 # base CDeclaratorNode
521 # args [CArgDeclNode]
522 # has_varargs boolean
523 # exception_value ConstNode
524 # exception_check boolean True if PyErr_Occurred check needed
525 # nogil boolean Can be called without gil
526 # with_gil boolean Acquire gil around function body
528 child_attrs = ["base", "args", "exception_value"]
530 overridable = 0
531 optional_arg_count = 0
533 def analyse(self, return_type, env, nonempty = 0):
534 if nonempty:
535 nonempty -= 1
536 func_type_args = []
537 for arg_node in self.args:
538 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
539 name = name_declarator.name
540 if name_declarator.cname:
541 error(self.pos,
542 "Function argument cannot have C name specification")
543 # Turn *[] argument into **
544 if type.is_array:
545 type = PyrexTypes.c_ptr_type(type.base_type)
546 # Catch attempted C-style func(void) decl
547 if type.is_void:
548 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
549 func_type_args.append(
550 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
551 if arg_node.default:
552 self.optional_arg_count += 1
553 elif self.optional_arg_count:
554 error(self.pos, "Non-default argument follows default argument")
556 if self.optional_arg_count:
557 scope = StructOrUnionScope()
558 arg_count_member = '%sn' % Naming.pyrex_prefix
559 scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
560 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
561 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
562 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
563 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
564 kind = 'struct',
565 scope = scope,
566 typedef_flag = 0,
567 pos = self.pos,
568 cname = struct_cname)
569 self.op_args_struct.defined_in_pxd = 1
570 self.op_args_struct.used = 1
572 exc_val = None
573 exc_check = 0
574 if self.exception_check == '+':
575 env.add_include_file('stdexcept')
576 if return_type.is_pyobject \
577 and (self.exception_value or self.exception_check) \
578 and self.exception_check != '+':
579 error(self.pos,
580 "Exception clause not allowed for function returning Python object")
581 else:
582 if self.exception_value:
583 self.exception_value.analyse_const_expression(env)
584 if self.exception_check == '+':
585 self.exception_value.analyse_types(env)
586 exc_val_type = self.exception_value.type
587 if not exc_val_type.is_error and \
588 not exc_val_type.is_pyobject and \
589 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
590 error(self.exception_value.pos,
591 "Exception value must be a Python exception or cdef function with no arguments.")
592 exc_val = self.exception_value
593 else:
594 if self.exception_value.analyse_const_expression(env):
595 exc_val = self.exception_value.get_constant_c_result_code()
596 if exc_val is None:
597 raise InternalError("get_constant_c_result_code not implemented for %s" %
598 self.exception_value.__class__.__name__)
599 if not return_type.assignable_from(self.exception_value.type):
600 error(self.exception_value.pos,
601 "Exception value incompatible with function return type")
602 exc_check = self.exception_check
603 if return_type.is_array:
604 error(self.pos,
605 "Function cannot return an array")
606 if return_type.is_cfunction:
607 error(self.pos,
608 "Function cannot return a function")
609 func_type = PyrexTypes.CFuncType(
610 return_type, func_type_args, self.has_varargs,
611 optional_arg_count = self.optional_arg_count,
612 exception_value = exc_val, exception_check = exc_check,
613 calling_convention = self.base.calling_convention,
614 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
615 if self.optional_arg_count:
616 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
617 callspec = env.directives['callspec']
618 if callspec:
619 current = func_type.calling_convention
620 if current and current != callspec:
621 error(self.pos, "cannot have both '%s' and '%s' "
622 "calling conventions" % (current, callspec))
623 func_type.calling_convention = callspec
624 return self.base.analyse(func_type, env)
627 class CArgDeclNode(Node):
628 # Item in a function declaration argument list.
629 #
630 # base_type CBaseTypeNode
631 # declarator CDeclaratorNode
632 # not_none boolean Tagged with 'not None'
633 # default ExprNode or None
634 # default_value PyObjectConst constant for default value
635 # is_self_arg boolean Is the "self" arg of an extension type method
636 # is_type_arg boolean Is the "class" arg of an extension type classmethod
637 # is_kw_only boolean Is a keyword-only argument
639 child_attrs = ["base_type", "declarator", "default"]
641 is_self_arg = 0
642 is_type_arg = 0
643 is_generic = 1
644 type = None
645 name_declarator = None
646 default_value = None
648 def analyse(self, env, nonempty = 0):
649 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
650 if self.type is None:
651 # The parser may missinterpret names as types...
652 # We fix that here.
653 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
654 if nonempty:
655 self.declarator.name = self.base_type.name
656 self.base_type.name = None
657 self.base_type.is_basic_c_type = False
658 could_be_name = True
659 else:
660 could_be_name = False
661 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
662 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
663 self.declarator.name = self.base_type.arg_name
664 # The parser is unable to resolve the ambiguity of [] as part of the
665 # type (e.g. in buffers) or empty declarator (as with arrays).
666 # This is only arises for empty multi-dimensional arrays.
667 if (base_type.is_array
668 and isinstance(self.base_type, TemplatedTypeNode)
669 and isinstance(self.declarator, CArrayDeclaratorNode)):
670 declarator = self.declarator
671 while isinstance(declarator.base, CArrayDeclaratorNode):
672 declarator = declarator.base
673 declarator.base = self.base_type.array_declarator
674 base_type = base_type.base_type
675 return self.declarator.analyse(base_type, env, nonempty = nonempty)
676 else:
677 return self.name_declarator, self.type
679 def calculate_default_value_code(self, code):
680 if self.default_value is None:
681 if self.default:
682 if self.default.is_literal:
683 # will not output any code, just assign the result_code
684 self.default.generate_evaluation_code(code)
685 return self.type.cast_code(self.default.result())
686 self.default_value = code.get_argument_default_const(self.type)
687 return self.default_value
689 def annotate(self, code):
690 if self.default:
691 self.default.annotate(code)
694 class CBaseTypeNode(Node):
695 # Abstract base class for C base type nodes.
696 #
697 # Processing during analyse_declarations phase:
698 #
699 # analyse
700 # Returns the type.
702 pass
704 def analyse_as_type(self, env):
705 return self.analyse(env)
707 class CAnalysedBaseTypeNode(Node):
708 # type type
710 child_attrs = []
712 def analyse(self, env, could_be_name = False):
713 return self.type
715 class CSimpleBaseTypeNode(CBaseTypeNode):
716 # name string
717 # module_path [string] Qualifying name components
718 # is_basic_c_type boolean
719 # signed boolean
720 # longness integer
721 # complex boolean
722 # is_self_arg boolean Is self argument of C method
723 # ##is_type_arg boolean Is type argument of class method
725 child_attrs = []
726 arg_name = None # in case the argument name was interpreted as a type
728 def analyse(self, env, could_be_name = False):
729 # Return type descriptor.
730 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
731 type = None
732 if self.is_basic_c_type:
733 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
734 if not type:
735 error(self.pos, "Unrecognised type modifier combination")
736 elif self.name == "object" and not self.module_path:
737 type = py_object_type
738 elif self.name is None:
739 if self.is_self_arg and env.is_c_class_scope:
740 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
741 type = env.parent_type
742 ## elif self.is_type_arg and env.is_c_class_scope:
743 ## type = Builtin.type_type
744 else:
745 type = py_object_type
746 else:
747 if self.module_path:
748 scope = env.find_imported_module(self.module_path, self.pos)
749 else:
750 scope = env
751 if scope:
752 if scope.is_c_class_scope:
753 scope = scope.global_scope()
754 entry = scope.lookup(self.name)
755 if entry and entry.is_type:
756 type = entry.type
757 elif could_be_name:
758 if self.is_self_arg and env.is_c_class_scope:
759 type = env.parent_type
760 ## elif self.is_type_arg and env.is_c_class_scope:
761 ## type = Builtin.type_type
762 else:
763 type = py_object_type
764 self.arg_name = self.name
765 else:
766 if self.templates:
767 if not self.name in self.templates:
768 error(self.pos, "'%s' is not a type identifier" % self.name)
769 type = PyrexTypes.TemplatePlaceholderType(self.name)
770 else:
771 error(self.pos, "'%s' is not a type identifier" % self.name)
772 if self.complex:
773 if not type.is_numeric or type.is_complex:
774 error(self.pos, "can only complexify c numeric types")
775 type = PyrexTypes.CComplexType(type)
776 type.create_declaration_utility_code(env)
777 if type:
778 return type
779 else:
780 return PyrexTypes.error_type
782 class CNestedBaseTypeNode(CBaseTypeNode):
783 # For C++ classes that live inside other C++ classes.
785 # name string
786 # base_type CBaseTypeNode
788 child_attrs = ['base_type']
790 def analyse(self, env, could_be_name = None):
791 base_type = self.base_type.analyse(env)
792 if base_type is PyrexTypes.error_type:
793 return PyrexTypes.error_type
794 if not base_type.is_cpp_class:
795 error(self.pos, "'%s' is not a valid type scope" % base_type)
796 return PyrexTypes.error_type
797 type_entry = base_type.scope.lookup_here(self.name)
798 if not type_entry or not type_entry.is_type:
799 error(self.pos, "'%s.%s' is not a type identifier" % (base_type, self.name))
800 return PyrexTypes.error_type
801 return type_entry.type
803 class TemplatedTypeNode(CBaseTypeNode):
804 # After parsing:
805 # positional_args [ExprNode] List of positional arguments
806 # keyword_args DictNode Keyword arguments
807 # base_type_node CBaseTypeNode
809 # After analysis:
810 # type PyrexTypes.BufferType or PyrexTypes.CppClassType ...containing the right options
813 child_attrs = ["base_type_node", "positional_args",
814 "keyword_args", "dtype_node"]
816 dtype_node = None
818 name = None
820 def analyse(self, env, could_be_name = False, base_type = None):
821 if base_type is None:
822 base_type = self.base_type_node.analyse(env)
823 if base_type.is_error: return base_type
825 if base_type.is_cpp_class:
826 # Templated class
827 if self.keyword_args and self.keyword_args.key_value_pairs:
828 error(self.pos, "c++ templates cannot take keyword arguments");
829 self.type = PyrexTypes.error_type
830 else:
831 template_types = []
832 for template_node in self.positional_args:
833 template_types.append(template_node.analyse_as_type(env))
834 self.type = base_type.specialize_here(self.pos, template_types)
836 elif base_type.is_pyobject:
837 # Buffer
838 import Buffer
840 options = Buffer.analyse_buffer_options(
841 self.pos,
842 env,
843 self.positional_args,
844 self.keyword_args,
845 base_type.buffer_defaults)
847 if sys.version_info[0] < 3:
848 # Py 2.x enforces byte strings as keyword arguments ...
849 options = dict([ (name.encode('ASCII'), value)
850 for name, value in options.iteritems() ])
852 self.type = PyrexTypes.BufferType(base_type, **options)
854 else:
855 # Array
856 empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
857 if len(self.positional_args) > 1 or self.keyword_args.key_value_pairs:
858 error(self.pos, "invalid array declaration")
859 self.type = PyrexTypes.error_type
860 else:
861 # It would be nice to merge this class with CArrayDeclaratorNode,
862 # but arrays are part of the declaration, not the type...
863 if not self.positional_args:
864 dimension = None
865 else:
866 dimension = self.positional_args[0]
867 self.array_declarator = CArrayDeclaratorNode(self.pos,
868 base = empty_declarator,
869 dimension = dimension)
870 self.type = self.array_declarator.analyse(base_type, env)[1]
872 return self.type
874 class CComplexBaseTypeNode(CBaseTypeNode):
875 # base_type CBaseTypeNode
876 # declarator CDeclaratorNode
878 child_attrs = ["base_type", "declarator"]
880 def analyse(self, env, could_be_name = False):
881 base = self.base_type.analyse(env, could_be_name)
882 _, type = self.declarator.analyse(base, env)
883 return type
886 class CVarDefNode(StatNode):
887 # C variable definition or forward/extern function declaration.
888 #
889 # visibility 'private' or 'public' or 'extern'
890 # base_type CBaseTypeNode
891 # declarators [CDeclaratorNode]
892 # in_pxd boolean
893 # api boolean
894 # properties [entry]
896 # decorators [cython.locals(...)] or None
897 # directive_locals { string : NameNode } locals defined by cython.locals(...)
899 child_attrs = ["base_type", "declarators"]
900 properties = ()
902 decorators = None
903 directive_locals = {}
905 def analyse_declarations(self, env, dest_scope = None):
906 if not dest_scope:
907 dest_scope = env
908 self.dest_scope = dest_scope
909 base_type = self.base_type.analyse(env)
911 # If the field is an external typedef, we cannot be sure about the type,
912 # so do conversion ourself rather than rely on the CPython mechanism (through
913 # a property; made in AnalyseDeclarationsTransform).
914 if (dest_scope.is_c_class_scope
915 and self.visibility in ('public', 'readonly')):
916 self.properties = []
917 need_property = True
918 else:
919 need_property = False
920 visibility = self.visibility
922 for declarator in self.declarators:
923 name_declarator, type = declarator.analyse(base_type, env)
924 if not type.is_complete():
925 if not (self.visibility == 'extern' and type.is_array):
926 error(declarator.pos,
927 "Variable type '%s' is incomplete" % type)
928 if self.visibility == 'extern' and type.is_pyobject:
929 error(declarator.pos,
930 "Python object cannot be declared extern")
931 name = name_declarator.name
932 cname = name_declarator.cname
933 if name == '':
934 error(declarator.pos, "Missing name in declaration.")
935 return
936 if type.is_cfunction:
937 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
938 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
939 api = self.api)
940 if entry is not None:
941 entry.directive_locals = self.directive_locals
942 else:
943 if self.directive_locals:
944 s.error("Decorators can only be followed by functions")
945 if self.in_pxd and self.visibility != 'extern':
946 error(self.pos,
947 "Only 'extern' C variable declaration allowed in .pxd file")
948 entry = dest_scope.declare_var(name, type, declarator.pos,
949 cname = cname, visibility = visibility, is_cdef = 1)
950 if need_property:
951 self.properties.append(entry)
954 class CStructOrUnionDefNode(StatNode):
955 # name string
956 # cname string or None
957 # kind "struct" or "union"
958 # typedef_flag boolean
959 # visibility "public" or "private"
960 # in_pxd boolean
961 # attributes [CVarDefNode] or None
962 # entry Entry
963 # packed boolean
965 child_attrs = ["attributes"]
967 def analyse_declarations(self, env):
968 scope = None
969 if self.visibility == 'extern' and self.packed:
970 error(self.pos, "Cannot declare extern struct as 'packed'")
971 if self.attributes is not None:
972 scope = StructOrUnionScope(self.name)
973 self.entry = env.declare_struct_or_union(
974 self.name, self.kind, scope, self.typedef_flag, self.pos,
975 self.cname, visibility = self.visibility, packed = self.packed)
976 if self.attributes is not None:
977 if self.in_pxd and not env.in_cinclude:
978 self.entry.defined_in_pxd = 1
979 for attr in self.attributes:
980 attr.analyse_declarations(env, scope)
981 if self.visibility != 'extern':
982 need_typedef_indirection = False
983 for attr in scope.var_entries:
984 type = attr.type
985 while type.is_array:
986 type = type.base_type
987 if type == self.entry.type:
988 error(attr.pos, "Struct cannot contain itself as a member.")
989 if self.typedef_flag:
990 while type.is_ptr:
991 type = type.base_type
992 if type == self.entry.type:
993 need_typedef_indirection = True
994 if need_typedef_indirection:
995 # C can't handle typedef structs that refer to themselves.
996 struct_entry = self.entry
997 self.entry = env.declare_typedef(
998 self.name, struct_entry.type, self.pos,
999 cname = self.cname, visibility='ignore')
1000 struct_entry.type.typedef_flag = False
1001 # FIXME: this might be considered a hack ;-)
1002 struct_entry.cname = struct_entry.type.cname = \
1003 '_' + self.entry.type.typedef_cname
1005 def analyse_expressions(self, env):
1006 pass
1008 def generate_execution_code(self, code):
1009 pass
1012 class CppClassNode(CStructOrUnionDefNode):
1014 # name string
1015 # cname string or None
1016 # visibility "extern"
1017 # in_pxd boolean
1018 # attributes [CVarDefNode] or None
1019 # entry Entry
1020 # base_classes [string]
1021 # templates [string] or None
1023 def analyse_declarations(self, env):
1024 scope = None
1025 if len(self.attributes) != 0:
1026 scope = CppClassScope(self.name, env)
1027 else:
1028 self.attributes = None
1029 base_class_types = []
1030 for base_class_name in self.base_classes:
1031 base_class_entry = env.lookup(base_class_name)
1032 if base_class_entry is None:
1033 error(self.pos, "'%s' not found" % base_class_name)
1034 elif not base_class_entry.is_type or not base_class_entry.type.is_cpp_class:
1035 error(self.pos, "'%s' is not a cpp class type" % base_class_name)
1036 else:
1037 base_class_types.append(base_class_entry.type)
1038 if self.templates is None:
1039 template_types = None
1040 else:
1041 template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1042 self.entry = env.declare_cpp_class(
1043 self.name, scope, self.pos,
1044 self.cname, base_class_types, visibility = self.visibility, templates = template_types)
1045 self.entry.is_cpp_class = 1
1046 if self.attributes is not None:
1047 if self.in_pxd and not env.in_cinclude:
1048 self.entry.defined_in_pxd = 1
1049 for attr in self.attributes:
1050 attr.analyse_declarations(scope)
1052 class CEnumDefNode(StatNode):
1053 # name string or None
1054 # cname string or None
1055 # items [CEnumDefItemNode]
1056 # typedef_flag boolean
1057 # visibility "public" or "private"
1058 # in_pxd boolean
1059 # entry Entry
1061 child_attrs = ["items"]
1063 def analyse_declarations(self, env):
1064 self.entry = env.declare_enum(self.name, self.pos,
1065 cname = self.cname, typedef_flag = self.typedef_flag,
1066 visibility = self.visibility)
1067 if self.items is not None:
1068 if self.in_pxd and not env.in_cinclude:
1069 self.entry.defined_in_pxd = 1
1070 for item in self.items:
1071 item.analyse_declarations(env, self.entry)
1073 def analyse_expressions(self, env):
1074 pass
1076 def generate_execution_code(self, code):
1077 if self.visibility == 'public':
1078 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
1079 for item in self.entry.enum_values:
1080 code.putln("%s = PyInt_FromLong(%s); %s" % (
1081 temp,
1082 item.cname,
1083 code.error_goto_if_null(temp, item.pos)))
1084 code.put_gotref(temp)
1085 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
1086 Naming.module_cname,
1087 item.name,
1088 temp,
1089 code.error_goto(item.pos)))
1090 code.put_decref_clear(temp, PyrexTypes.py_object_type)
1091 code.funcstate.release_temp(temp)
1094 class CEnumDefItemNode(StatNode):
1095 # name string
1096 # cname string or None
1097 # value ExprNode or None
1099 child_attrs = ["value"]
1101 def analyse_declarations(self, env, enum_entry):
1102 if self.value:
1103 self.value.analyse_const_expression(env)
1104 if not self.value.type.is_int:
1105 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
1106 self.value.analyse_const_expression(env)
1107 entry = env.declare_const(self.name, enum_entry.type,
1108 self.value, self.pos, cname = self.cname,
1109 visibility = enum_entry.visibility)
1110 enum_entry.enum_values.append(entry)
1113 class CTypeDefNode(StatNode):
1114 # base_type CBaseTypeNode
1115 # declarator CDeclaratorNode
1116 # visibility "public" or "private"
1117 # in_pxd boolean
1119 child_attrs = ["base_type", "declarator"]
1121 def analyse_declarations(self, env):
1122 base = self.base_type.analyse(env)
1123 name_declarator, type = self.declarator.analyse(base, env)
1124 name = name_declarator.name
1125 cname = name_declarator.cname
1126 entry = env.declare_typedef(name, type, self.pos,
1127 cname = cname, visibility = self.visibility)
1128 if self.in_pxd and not env.in_cinclude:
1129 entry.defined_in_pxd = 1
1131 def analyse_expressions(self, env):
1132 pass
1133 def generate_execution_code(self, code):
1134 pass
1137 class FuncDefNode(StatNode, BlockNode):
1138 # Base class for function definition nodes.
1140 # return_type PyrexType
1141 # #filename string C name of filename string const
1142 # entry Symtab.Entry
1143 # needs_closure boolean Whether or not this function has inner functions/classes/yield
1144 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1146 py_func = None
1147 assmt = None
1148 needs_closure = False
1149 modifiers = []
1151 def analyse_default_values(self, env):
1152 genv = env.global_scope()
1153 default_seen = 0
1154 for arg in self.args:
1155 if arg.default:
1156 default_seen = 1
1157 if arg.is_generic:
1158 arg.default.analyse_types(env)
1159 arg.default = arg.default.coerce_to(arg.type, genv)
1160 else:
1161 error(arg.pos,
1162 "This argument cannot have a default value")
1163 arg.default = None
1164 elif arg.kw_only:
1165 default_seen = 1
1166 elif default_seen:
1167 error(arg.pos, "Non-default argument following default argument")
1169 def need_gil_acquisition(self, lenv):
1170 return 0
1172 def create_local_scope(self, env):
1173 genv = env
1174 while genv.is_py_class_scope or genv.is_c_class_scope:
1175 genv = env.outer_scope
1176 if self.needs_closure:
1177 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1178 else:
1179 lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1180 lenv.return_type = self.return_type
1181 type = self.entry.type
1182 if type.is_cfunction:
1183 lenv.nogil = type.nogil and not type.with_gil
1184 self.local_scope = lenv
1185 lenv.directives = env.directives
1186 return lenv
1188 def generate_function_definitions(self, env, code):
1189 import Buffer
1191 lenv = self.local_scope
1193 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1194 self.entry.scope.is_c_class_scope)
1196 profile = code.globalstate.directives['profile']
1197 if profile:
1198 if lenv.nogil:
1199 error(self.pos, "Cannot profile nogil function.")
1200 code.globalstate.use_utility_code(profile_utility_code)
1202 # Generate C code for header and body of function
1203 code.enter_cfunc_scope()
1204 code.return_from_error_cleanup_label = code.new_label()
1206 # ----- Top-level constants used by this function
1207 code.mark_pos(self.pos)
1208 self.generate_cached_builtins_decls(lenv, code)
1209 # ----- Function header
1210 code.putln("")
1211 if self.py_func:
1212 self.py_func.generate_function_header(code,
1213 with_pymethdef = env.is_py_class_scope,
1214 proto_only=True)
1215 self.generate_function_header(code,
1216 with_pymethdef = env.is_py_class_scope)
1217 # ----- Local variable declarations
1218 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1219 self.generate_argument_declarations(lenv, code)
1220 if self.needs_closure:
1221 code.putln("/* TODO: declare and create scope object */")
1222 code.put_var_declarations(lenv.var_entries)
1223 init = ""
1224 if not self.return_type.is_void:
1225 if self.return_type.is_pyobject:
1226 init = " = NULL"
1227 code.putln(
1228 "%s%s;" %
1229 (self.return_type.declaration_code(
1230 Naming.retval_cname),
1231 init))
1232 tempvardecl_code = code.insertion_point()
1233 self.generate_keyword_list(code)
1234 if profile:
1235 code.put_trace_declarations()
1236 # ----- Extern library function declarations
1237 lenv.generate_library_function_declarations(code)
1238 # ----- GIL acquisition
1239 acquire_gil = self.acquire_gil
1240 if acquire_gil:
1241 env.use_utility_code(force_init_threads_utility_code)
1242 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1243 # ----- Automatic lead-ins for certain special functions
1244 if not lenv.nogil:
1245 code.put_setup_refcount_context(self.entry.name)
1246 if profile:
1247 code.put_trace_call(self.entry.name, self.pos)
1248 if is_getbuffer_slot:
1249 self.getbuffer_init(code)
1250 # ----- Fetch arguments
1251 self.generate_argument_parsing_code(env, code)
1252 # If an argument is assigned to in the body, we must
1253 # incref it to properly keep track of refcounts.
1254 for entry in lenv.arg_entries:
1255 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1256 code.put_var_incref(entry)
1257 # ----- Initialise local variables
1258 for entry in lenv.var_entries:
1259 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1260 code.put_init_var_to_py_none(entry)
1261 # ----- Initialise local buffer auxiliary variables
1262 for entry in lenv.var_entries + lenv.arg_entries:
1263 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1264 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1265 # ----- Check and convert arguments
1266 self.generate_argument_type_tests(code)
1267 # ----- Acquire buffer arguments
1268 for entry in lenv.arg_entries:
1269 if entry.type.is_buffer:
1270 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1271 # ----- Function body
1272 self.body.generate_execution_code(code)
1273 # ----- Default return value
1274 code.putln("")
1275 if self.return_type.is_pyobject:
1276 #if self.return_type.is_extension_type:
1277 # lhs = "(PyObject *)%s" % Naming.retval_cname
1278 #else:
1279 lhs = Naming.retval_cname
1280 code.put_init_to_py_none(lhs, self.return_type)
1281 else:
1282 val = self.return_type.default_value
1283 if val:
1284 code.putln("%s = %s;" % (Naming.retval_cname, val))
1285 # ----- Error cleanup
1286 if code.error_label in code.labels_used:
1287 code.put_goto(code.return_label)
1288 code.put_label(code.error_label)
1289 for cname, type in code.funcstate.all_managed_temps():
1290 code.put_xdecref(cname, type)
1292 # Clean up buffers -- this calls a Python function
1293 # so need to save and restore error state
1294 buffers_present = len(lenv.buffer_entries) > 0
1295 if buffers_present:
1296 code.globalstate.use_utility_code(restore_exception_utility_code)
1297 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1298 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1299 for entry in lenv.buffer_entries:
1300 Buffer.put_release_buffer_code(code, entry)
1301 #code.putln("%s = 0;" % entry.cname)
1302 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1304 err_val = self.error_value()
1305 exc_check = self.caller_will_check_exceptions()
1306 if err_val is not None or exc_check:
1307 # TODO: Fix exception tracing (though currently unused by cProfile).
1308 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1309 # code.put_trace_exception()
1310 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1311 else:
1312 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1313 % self.entry.qualified_name, 0)
1314 code.putln(
1315 '__Pyx_WriteUnraisable("%s");' %
1316 self.entry.qualified_name)
1317 env.use_utility_code(unraisable_exception_utility_code)
1318 env.use_utility_code(restore_exception_utility_code)
1319 default_retval = self.return_type.default_value
1320 if err_val is None and default_retval:
1321 err_val = default_retval
1322 if err_val is not None:
1323 code.putln(
1324 "%s = %s;" % (
1325 Naming.retval_cname,
1326 err_val))
1328 if is_getbuffer_slot:
1329 self.getbuffer_error_cleanup(code)
1331 # If we are using the non-error cleanup section we should
1332 # jump past it if we have an error. The if-test below determine
1333 # whether this section is used.
1334 if buffers_present or is_getbuffer_slot:
1335 code.put_goto(code.return_from_error_cleanup_label)
1338 # ----- Non-error return cleanup
1339 code.put_label(code.return_label)
1340 for entry in lenv.buffer_entries:
1341 if entry.used:
1342 Buffer.put_release_buffer_code(code, entry)
1343 if is_getbuffer_slot:
1344 self.getbuffer_normal_cleanup(code)
1345 # ----- Return cleanup for both error and no-error return
1346 code.put_label(code.return_from_error_cleanup_label)
1347 if not Options.init_local_none:
1348 for entry in lenv.var_entries:
1349 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1350 entry.xdecref_cleanup = 1
1351 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1352 # Decref any increfed args
1353 for entry in lenv.arg_entries:
1354 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1355 code.put_var_decref(entry)
1357 # code.putln("/* TODO: decref scope object */")
1358 # ----- Return
1359 # This code is duplicated in ModuleNode.generate_module_init_func
1360 if not lenv.nogil:
1361 default_retval = self.return_type.default_value
1362 err_val = self.error_value()
1363 if err_val is None and default_retval:
1364 err_val = default_retval
1365 if self.return_type.is_pyobject:
1366 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1368 if self.entry.is_special and self.entry.name == "__hash__":
1369 # Returning -1 for __hash__ is supposed to signal an error
1370 # We do as Python instances and coerce -1 into -2.
1371 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1372 Naming.retval_cname, Naming.retval_cname))
1374 if profile:
1375 if self.return_type.is_pyobject:
1376 code.put_trace_return(Naming.retval_cname)
1377 else:
1378 code.put_trace_return("Py_None")
1379 if not lenv.nogil:
1380 code.put_finish_refcount_context()
1382 if acquire_gil:
1383 code.putln("PyGILState_Release(_save);")
1385 if not self.return_type.is_void:
1386 code.putln("return %s;" % Naming.retval_cname)
1388 code.putln("}")
1389 # ----- Go back and insert temp variable declarations
1390 tempvardecl_code.put_temp_declarations(code.funcstate)
1391 # ----- Python version
1392 code.exit_cfunc_scope()
1393 if self.py_func:
1394 self.py_func.generate_function_definitions(env, code)
1395 self.generate_wrapper_functions(code)
1397 def declare_argument(self, env, arg):
1398 if arg.type.is_void:
1399 error(arg.pos, "Invalid use of 'void'")
1400 elif not arg.type.is_complete() and not arg.type.is_array:
1401 error(arg.pos,
1402 "Argument type '%s' is incomplete" % arg.type)
1403 return env.declare_arg(arg.name, arg.type, arg.pos)
1405 def generate_wrapper_functions(self, code):
1406 pass
1408 def generate_execution_code(self, code):
1409 # Evaluate and store argument default values
1410 for arg in self.args:
1411 default = arg.default
1412 if default:
1413 if not default.is_literal:
1414 default.generate_evaluation_code(code)
1415 default.make_owned_reference(code)
1416 result = default.result_as(arg.type)
1417 code.putln(
1418 "%s = %s;" % (
1419 arg.calculate_default_value_code(code),
1420 result))
1421 if arg.type.is_pyobject:
1422 code.put_giveref(default.result())
1423 default.generate_post_assignment_code(code)
1424 default.free_temps(code)
1425 # For Python class methods, create and store function object
1426 if self.assmt:
1427 self.assmt.generate_execution_code(code)
1430 # Special code for the __getbuffer__ function
1432 def getbuffer_init(self, code):
1433 info = self.local_scope.arg_entries[1].cname
1434 # Python 3.0 betas have a bug in memoryview which makes it call
1435 # getbuffer with a NULL parameter. For now we work around this;
1436 # the following line should be removed when this bug is fixed.
1437 code.putln("if (%s == NULL) return 0;" % info)
1438 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1439 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1441 def getbuffer_error_cleanup(self, code):
1442 info = self.local_scope.arg_entries[1].cname
1443 code.put_gotref("%s->obj" % info)
1444 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1445 (info, info))
1447 def getbuffer_normal_cleanup(self, code):
1448 info = self.local_scope.arg_entries[1].cname
1449 code.putln("if (%s->obj == Py_None) {" % info)
1450 code.put_gotref("Py_None")
1451 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1452 code.putln("}")
1454 class CFuncDefNode(FuncDefNode):
1455 # C function definition.
1457 # modifiers ['inline']
1458 # visibility 'private' or 'public' or 'extern'
1459 # base_type CBaseTypeNode
1460 # declarator CDeclaratorNode
1461 # body StatListNode
1462 # api boolean
1463 # decorators [DecoratorNode] list of decorators
1465 # with_gil boolean Acquire GIL around body
1466 # type CFuncType
1467 # py_func wrapper for calling from Python
1468 # overridable whether or not this is a cpdef function
1469 # inline_in_pxd whether this is an inline function in a pxd file
1471 child_attrs = ["base_type", "declarator", "body", "py_func"]
1473 inline_in_pxd = False
1474 decorators = None
1475 directive_locals = {}
1477 def unqualified_name(self):
1478 return self.entry.name
1480 def analyse_declarations(self, env):
1481 self.directive_locals.update(env.directives['locals'])
1482 base_type = self.base_type.analyse(env)
1483 # The 2 here is because we need both function and argument names.
1484 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1485 if not type.is_cfunction:
1486 error(self.pos,
1487 "Suite attached to non-function declaration")
1488 # Remember the actual type according to the function header
1489 # written here, because the type in the symbol table entry
1490 # may be different if we're overriding a C method inherited
1491 # from the base type of an extension type.
1492 self.type = type
1493 type.is_overridable = self.overridable
1494 declarator = self.declarator
1495 while not hasattr(declarator, 'args'):
1496 declarator = declarator.base
1497 self.args = declarator.args
1498 for formal_arg, type_arg in zip(self.args, type.args):
1499 formal_arg.type = type_arg.type
1500 formal_arg.name = type_arg.name
1501 formal_arg.cname = type_arg.cname
1502 name = name_declarator.name
1503 cname = name_declarator.cname
1504 self.entry = env.declare_cfunction(
1505 name, type, self.pos,
1506 cname = cname, visibility = self.visibility,
1507 defining = self.body is not None,
1508 api = self.api, modifiers = self.modifiers)
1509 self.entry.inline_func_in_pxd = self.inline_in_pxd
1510 self.return_type = type.return_type
1512 if self.overridable and not env.is_module_scope:
1513 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1514 # An error will be produced in the cdef function
1515 self.overridable = False
1517 if self.overridable:
1518 import ExprNodes
1519 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1520 self.py_func = DefNode(pos = self.pos,
1521 name = self.entry.name,
1522 args = self.args,
1523 star_arg = None,
1524 starstar_arg = None,
1525 doc = self.doc,
1526 body = py_func_body,
1527 is_wrapper = 1)
1528 self.py_func.is_module_scope = env.is_module_scope
1529 self.py_func.analyse_declarations(env)
1530 self.entry.as_variable = self.py_func.entry
1531 # Reset scope entry the above cfunction
1532 env.entries[name] = self.entry
1533 if not env.is_module_scope or Options.lookup_module_cpdef:
1534 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1535 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1536 self.create_local_scope(env)
1538 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1539 import ExprNodes
1540 args = self.type.args
1541 if omit_optional_args:
1542 args = args[:len(args) - self.type.optional_arg_count]
1543 arg_names = [arg.name for arg in args]
1544 if is_module_scope:
1545 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1546 else:
1547 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1548 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1549 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1550 c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch)
1551 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1553 def declare_arguments(self, env):
1554 for arg in self.type.args:
1555 if not arg.name:
1556 error(arg.pos, "Missing argument name")
1557 self.declare_argument(env, arg)
1559 def need_gil_acquisition(self, lenv):
1560 return self.type.with_gil
1562 def nogil_check(self, env):
1563 type = self.type
1564 with_gil = type.with_gil
1565 if type.nogil and not with_gil:
1566 if type.return_type.is_pyobject:
1567 error(self.pos,
1568 "Function with Python return type cannot be declared nogil")
1569 for entry in self.local_scope.var_entries:
1570 if entry.type.is_pyobject:
1571 error(self.pos, "Function declared nogil has Python locals or temporaries")
1573 def analyse_expressions(self, env):
1574 self.local_scope.directives = env.directives
1575 if self.py_func is not None:
1576 # this will also analyse the default values
1577 self.py_func.analyse_expressions(env)
1578 else:
1579 self.analyse_default_values(env)
1580 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1582 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1583 arg_decls = []
1584 type = self.type
1585 visibility = self.entry.visibility
1586 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1587 arg_decls.append(arg.declaration_code())
1588 if with_dispatch and self.overridable:
1589 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1590 if type.optional_arg_count and with_opt_args:
1591 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1592 if type.has_varargs:
1593 arg_decls.append("...")
1594 if not arg_decls:
1595 arg_decls = ["void"]
1596 if cname is None:
1597 cname = self.entry.func_cname
1598 entity = type.function_header_code(cname, ', '.join(arg_decls))
1599 if visibility == 'public':
1600 dll_linkage = "DL_EXPORT"
1601 else:
1602 dll_linkage = None
1603 header = self.return_type.declaration_code(entity,
1604 dll_linkage = dll_linkage)
1605 if visibility == 'extern':
1606 storage_class = "%s " % Naming.extern_c_macro
1607 elif visibility == 'public':
1608 storage_class = ""
1609 else:
1610 storage_class = "static "
1611 if 'inline' in self.modifiers:
1612 self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
1613 code.putln("%s%s %s {" % (
1614 storage_class,
1615 ' '.join(self.modifiers).upper(), # macro forms
1616 header))
1618 def generate_argument_declarations(self, env, code):
1619 for arg in self.args:
1620 if arg.default:
1621 result = arg.calculate_default_value_code(code)
1622 code.putln('%s = %s;' % (
1623 arg.type.declaration_code(arg.cname), result))
1625 def generate_keyword_list(self, code):
1626 pass
1628 def generate_argument_parsing_code(self, env, code):
1629 i = 0
1630 if self.type.optional_arg_count:
1631 code.putln('if (%s) {' % Naming.optional_args_cname)
1632 for arg in self.args:
1633 if arg.default:
1634 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1635 declarator = arg.declarator
1636 while not hasattr(declarator, 'name'):
1637 declarator = declarator.base
1638 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1639 i += 1
1640 for _ in range(self.type.optional_arg_count):
1641 code.putln('}')
1642 code.putln('}')
1644 def generate_argument_conversion_code(self, code):
1645 pass
1647 def generate_argument_type_tests(self, code):
1648 # Generate type tests for args whose type in a parent
1649 # class is a supertype of the declared type.
1650 for arg in self.type.args:
1651 if arg.needs_type_test:
1652 self.generate_arg_type_test(arg, code)
1654 def generate_arg_type_test(self, arg, code):
1655 # Generate type test for one argument.
1656 if arg.type.typeobj_is_available():
1657 typeptr_cname = arg.type.typeptr_cname
1658 arg_code = "((PyObject *)%s)" % arg.cname
1659 code.putln(
1660 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1661 arg_code,
1662 typeptr_cname,
1663 not arg.not_none,
1664 arg.name,
1665 type.is_builtin_type,
1666 code.error_goto(arg.pos)))
1667 else:
1668 error(arg.pos, "Cannot test type of extern C class "
1669 "without type object name specification")
1671 def error_value(self):
1672 if self.return_type.is_pyobject:
1673 return "0"
1674 else:
1675 #return None
1676 return self.entry.type.exception_value
1678 def caller_will_check_exceptions(self):
1679 return self.entry.type.exception_check
1681 def generate_wrapper_functions(self, code):
1682 # If the C signature of a function has changed, we need to generate
1683 # wrappers to put in the slots here.
1684 k = 0
1685 entry = self.entry
1686 func_type = entry.type
1687 while entry.prev_entry is not None:
1688 k += 1
1689 entry = entry.prev_entry
1690 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1691 code.putln()
1692 self.generate_function_header(code,
1693 0,
1694 with_dispatch = entry.type.is_overridable,
1695 with_opt_args = entry.type.optional_arg_count,
1696 cname = entry.func_cname)
1697 if not self.return_type.is_void:
1698 code.put('return ')
1699 args = self.type.args
1700 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1701 if entry.type.is_overridable:
1702 arglist.append(Naming.skip_dispatch_cname)
1703 elif func_type.is_overridable:
1704 arglist.append('0')
1705 if entry.type.optional_arg_count:
1706 arglist.append(Naming.optional_args_cname)
1707 elif func_type.optional_arg_count:
1708 arglist.append('NULL')
1709 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1710 code.putln('}')
1713 class PyArgDeclNode(Node):
1714 # Argument which must be a Python object (used
1715 # for * and ** arguments).
1717 # name string
1718 # entry Symtab.Entry
1719 child_attrs = []
1722 class DecoratorNode(Node):
1723 # A decorator
1725 # decorator NameNode or CallNode or AttributeNode
1726 child_attrs = ['decorator']
1729 class DefNode(FuncDefNode):
1730 # A Python function definition.
1732 # name string the Python name of the function
1733 # decorators [DecoratorNode] list of decorators
1734 # args [CArgDeclNode] formal arguments
1735 # star_arg PyArgDeclNode or None * argument
1736 # starstar_arg PyArgDeclNode or None ** argument
1737 # doc EncodedString or None
1738 # body StatListNode
1740 # The following subnode is constructed internally
1741 # when the def statement is inside a Python class definition.
1743 # assmt AssignmentNode Function construction/assignment
1745 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1747 assmt = None
1748 num_kwonly_args = 0
1749 num_required_kw_args = 0
1750 reqd_kw_flags_cname = "0"
1751 is_wrapper = 0
1752 decorators = None
1753 entry = None
1754 acquire_gil = 0
1755 self_in_stararg = 0
1757 def __init__(self, pos, **kwds):
1758 FuncDefNode.__init__(self, pos, **kwds)
1759 k = rk = r = 0
1760 for arg in self.args:
1761 if arg.kw_only:
1762 k += 1
1763 if not arg.default:
1764 rk += 1
1765 if not arg.default:
1766 r += 1
1767 self.num_kwonly_args = k
1768 self.num_required_kw_args = rk
1769 self.num_required_args = r
1771 def as_cfunction(self, cfunc=None, scope=None):
1772 if self.star_arg:
1773 error(self.star_arg.pos, "cdef function cannot have star argument")
1774 if self.starstar_arg:
1775 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1776 if cfunc is None:
1777 cfunc_args = []
1778 for formal_arg in self.args:
1779 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1780 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1781 cname = None,
1782 type = py_object_type,
1783 pos = formal_arg.pos))
1784 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1785 args = cfunc_args,
1786 has_varargs = False,
1787 exception_value = None,
1788 exception_check = False,
1789 nogil = False,
1790 with_gil = False,
1791 is_overridable = True)
1792 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1793 else:
1794 cfunc_type = cfunc.type
1795 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1796 error(self.pos, "wrong number of arguments")
1797 error(cfunc.pos, "previous declaration here")
1798 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1799 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1800 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1801 formal_arg.type = type_arg.type
1802 formal_arg.name_declarator = name_declarator
1803 import ExprNodes
1804 if cfunc_type.exception_value is None:
1805 exception_value = None
1806 else:
1807 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1808 declarator = CFuncDeclaratorNode(self.pos,
1809 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1810 args = self.args,
1811 has_varargs = False,
1812 exception_check = cfunc_type.exception_check,
1813 exception_value = exception_value,
1814 with_gil = cfunc_type.with_gil,
1815 nogil = cfunc_type.nogil)
1816 return CFuncDefNode(self.pos,
1817 modifiers = [],
1818 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1819 declarator = declarator,
1820 body = self.body,
1821 doc = self.doc,
1822 overridable = cfunc_type.is_overridable,
1823 type = cfunc_type,
1824 with_gil = cfunc_type.with_gil,
1825 nogil = cfunc_type.nogil,
1826 visibility = 'private',
1827 api = False,
1828 directive_locals = getattr(cfunc, 'directive_locals', {}))
1830 def analyse_declarations(self, env):
1831 self.is_classmethod = self.is_staticmethod = False
1832 if self.decorators:
1833 for decorator in self.decorators:
1834 func = decorator.decorator
1835 if func.is_name:
1836 self.is_classmethod |= func.name == 'classmethod'
1837 self.is_staticmethod |= func.name == 'staticmethod'
1839 if self.is_classmethod and env.lookup_here('classmethod'):
1840 # classmethod() was overridden - not much we can do here ...
1841 self.is_classmethod = False
1842 if self.is_staticmethod and env.lookup_here('staticmethod'):
1843 # staticmethod() was overridden - not much we can do here ...
1844 self.is_staticmethod = False
1846 self.analyse_argument_types(env)
1847 self.declare_pyfunction(env)
1848 self.analyse_signature(env)
1849 self.return_type = self.entry.signature.return_type()
1850 self.create_local_scope(env)
1852 def analyse_argument_types(self, env):
1853 directive_locals = self.directive_locals = env.directives['locals']
1854 for arg in self.args:
1855 if hasattr(arg, 'name'):
1856 type = arg.type
1857 name_declarator = None
1858 else:
1859 base_type = arg.base_type.analyse(env)
1860 name_declarator, type = \
1861 arg.declarator.analyse(base_type, env)
1862 arg.name = name_declarator.name
1863 if arg.name in directive_locals:
1864 type_node = directive_locals[arg.name]
1865 other_type = type_node.analyse_as_type(env)
1866 if other_type is None:
1867 error(type_node.pos, "Not a type")
1868 elif (type is not PyrexTypes.py_object_type
1869 and not type.same_as(other_type)):
1870 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1871 error(type_node.pos, "Previous declaration here")
1872 else:
1873 type = other_type
1874 if name_declarator and name_declarator.cname:
1875 error(self.pos,
1876 "Python function argument cannot have C name specification")
1877 arg.type = type.as_argument_type()
1878 arg.hdr_type = None
1879 arg.needs_conversion = 0
1880 arg.needs_type_test = 0
1881 arg.is_generic = 1
1882 if arg.not_none and not arg.type.is_extension_type:
1883 error(self.pos,
1884 "Only extension type arguments can have 'not None'")
1886 def analyse_signature(self, env):
1887 any_type_tests_needed = 0
1888 if self.entry.is_special:
1889 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1890 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1891 # Use the simpler calling signature for zero- and one-argument functions.
1892 if self.entry.signature is TypeSlots.pyfunction_signature:
1893 if len(self.args) == 0:
1894 self.entry.signature = TypeSlots.pyfunction_noargs
1895 elif len(self.args) == 1:
1896 if self.args[0].default is None and not self.args[0].kw_only:
1897 self.entry.signature = TypeSlots.pyfunction_onearg
1898 elif self.entry.signature is TypeSlots.pymethod_signature:
1899 if len(self.args) == 1:
1900 self.entry.signature = TypeSlots.unaryfunc
1901 elif len(self.args) == 2:
1902 if self.args[1].default is None and not self.args[1].kw_only:
1903 self.entry.signature = TypeSlots.ibinaryfunc
1905 sig = self.entry.signature
1906 nfixed = sig.num_fixed_args()
1907 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
1908 and len(self.args) == 0 and self.star_arg:
1909 # this is the only case where a diverging number of
1910 # arguments is not an error - when we have no explicit
1911 # 'self' parameter as in method(*args)
1912 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
1913 self.self_in_stararg = 1
1914 nfixed = 0
1916 for i in range(min(nfixed, len(self.args))):
1917 arg = self.args[i]
1918 arg.is_generic = 0
1919 if sig.is_self_arg(i) and not self.is_staticmethod:
1920 if self.is_classmethod:
1921 arg.is_type_arg = 1
1922 arg.hdr_type = arg.type = Builtin.type_type
1923 else:
1924 arg.is_self_arg = 1
1925 arg.hdr_type = arg.type = env.parent_type
1926 arg.needs_conversion = 0
1927 else:
1928 arg.hdr_type = sig.fixed_arg_type(i)
1929 if not arg.type.same_as(arg.hdr_type):
1930 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1931 arg.needs_type_test = 1
1932 any_type_tests_needed = 1
1933 else:
1934 arg.needs_conversion = 1
1935 if arg.needs_conversion:
1936 arg.hdr_cname = Naming.arg_prefix + arg.name
1937 else:
1938 arg.hdr_cname = Naming.var_prefix + arg.name
1940 if nfixed > len(self.args):
1941 self.bad_signature()
1942 return
1943 elif nfixed < len(self.args):
1944 if not sig.has_generic_args:
1945 self.bad_signature()
1946 for arg in self.args:
1947 if arg.is_generic and \
1948 (arg.type.is_extension_type or arg.type.is_builtin_type):
1949 arg.needs_type_test = 1
1950 any_type_tests_needed = 1
1951 if any_type_tests_needed:
1952 env.use_utility_code(arg_type_test_utility_code)
1954 def bad_signature(self):
1955 sig = self.entry.signature
1956 expected_str = "%d" % sig.num_fixed_args()
1957 if sig.has_generic_args:
1958 expected_str = expected_str + " or more"
1959 name = self.name
1960 if name.startswith("__") and name.endswith("__"):
1961 desc = "Special method"
1962 else:
1963 desc = "Method"
1964 error(self.pos,
1965 "%s %s has wrong number of arguments "
1966 "(%d declared, %s expected)" % (
1967 desc, self.name, len(self.args), expected_str))
1969 def signature_has_nongeneric_args(self):
1970 argcount = len(self.args)
1971 if argcount == 0 or (
1972 argcount == 1 and (self.args[0].is_self_arg or
1973 self.args[0].is_type_arg)):
1974 return 0
1975 return 1
1977 def signature_has_generic_args(self):
1978 return self.entry.signature.has_generic_args
1980 def declare_pyfunction(self, env):
1981 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1982 name = self.name
1983 entry = env.lookup_here(self.name)
1984 if entry and entry.type.is_cfunction and not self.is_wrapper:
1985 warning(self.pos, "Overriding cdef method with def method.", 5)
1986 entry = env.declare_pyfunction(self.name, self.pos)
1987 self.entry = entry
1988 prefix = env.scope_prefix
1989 entry.func_cname = \
1990 Naming.pyfunc_prefix + prefix + name
1991 entry.pymethdef_cname = \
1992 Naming.pymethdef_prefix + prefix + name
1993 if Options.docstrings:
1994 entry.doc = embed_position(self.pos, self.doc)
1995 entry.doc_cname = \
1996 Naming.funcdoc_prefix + prefix + name
1997 else:
1998 entry.doc = None
2000 def declare_arguments(self, env):
2001 for arg in self.args:
2002 if not arg.name:
2003 error(arg.pos, "Missing argument name")
2004 if arg.needs_conversion:
2005 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
2006 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
2007 env.control_flow.set_state((), (arg.name, 'initalized'), True)
2008 if arg.type.is_pyobject:
2009 arg.entry.init = "0"
2010 arg.entry.init_to_none = 0
2011 else:
2012 arg.entry = self.declare_argument(env, arg)
2013 arg.entry.used = 1
2014 arg.entry.is_self_arg = arg.is_self_arg
2015 if arg.hdr_type:
2016 if arg.is_self_arg or arg.is_type_arg or \
2017 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
2018 arg.entry.is_declared_generic = 1
2019 self.declare_python_arg(env, self.star_arg)
2020 self.declare_python_arg(env, self.starstar_arg)
2022 def declare_python_arg(self, env, arg):
2023 if arg:
2024 if env.directives['infer_types'] != False:
2025 type = PyrexTypes.unspecified_type
2026 else:
2027 type = py_object_type
2028 entry = env.declare_var(arg.name, type, arg.pos)
2029 entry.used = 1
2030 entry.init = "0"
2031 entry.init_to_none = 0
2032 entry.xdecref_cleanup = 1
2033 arg.entry = entry
2034 env.control_flow.set_state((), (arg.name, 'initalized'), True)
2036 def analyse_expressions(self, env):
2037 self.local_scope.directives = env.directives
2038 self.analyse_default_values(env)
2039 if env.is_py_class_scope:
2040 self.synthesize_assignment_node(env)
2042 def synthesize_assignment_node(self, env):
2043 import ExprNodes
2044 self.assmt = SingleAssignmentNode(self.pos,
2045 lhs = ExprNodes.NameNode(self.pos, name = self.name),
2046 rhs = ExprNodes.UnboundMethodNode(self.pos,
2047 function = ExprNodes.PyCFunctionNode(self.pos,
2048 pymethdef_cname = self.entry.pymethdef_cname)))
2049 self.assmt.analyse_declarations(env)
2050 self.assmt.analyse_expressions(env)
2052 def generate_function_header(self, code, with_pymethdef, proto_only=0):
2053 arg_code_list = []
2054 sig = self.entry.signature
2055 if sig.has_dummy_arg or self.self_in_stararg:
2056 arg_code_list.append(
2057 "PyObject *%s" % Naming.self_cname)
2058 for arg in self.args:
2059 if not arg.is_generic:
2060 if arg.is_self_arg or arg.is_type_arg:
2061 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
2062 else:
2063 arg_code_list.append(
2064 arg.hdr_type.declaration_code(arg.hdr_cname))
2065 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
2066 arg_code_list.append("PyObject *unused")
2067 if sig.has_generic_args:
2068 arg_code_list.append(
2069 "PyObject *%s, PyObject *%s"
2070 % (Naming.args_cname, Naming.kwds_cname))
2071 arg_code = ", ".join(arg_code_list)
2072 dc = self.return_type.declaration_code(self.entry.func_cname)
2073 header = "static %s(%s)" % (dc, arg_code)
2074 code.putln("%s; /*proto*/" % header)
2075 if proto_only:
2076 return
2077 if self.entry.doc and Options.docstrings:
2078 docstr = self.entry.doc
2079 if docstr.is_unicode:
2080 docstr = docstr.utf8encode()
2081 code.putln(
2082 'static char %s[] = "%s";' % (
2083 self.entry.doc_cname,
2084 split_string_literal(escape_byte_string(docstr))))
2085 if with_pymethdef:
2086 code.put(
2087 "static PyMethodDef %s = " %
2088 self.entry.pymethdef_cname)
2089 code.put_pymethoddef(self.entry, ";")
2090 code.putln("%s {" % header)
2092 def generate_argument_declarations(self, env, code):
2093 for arg in self.args:
2094 if arg.is_generic: # or arg.needs_conversion:
2095 if arg.needs_conversion:
2096 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
2097 else:
2098 code.put_var_declaration(arg.entry)
2100 def generate_keyword_list(self, code):
2101 if self.signature_has_generic_args() and \
2102 self.signature_has_nongeneric_args():
2103 code.put(
2104 "static PyObject **%s[] = {" %
2105 Naming.pykwdlist_cname)
2106 for arg in self.args:
2107 if arg.is_generic:
2108 pystring_cname = code.intern_identifier(arg.name)
2109 code.put('&%s,' % pystring_cname)
2110 code.putln("0};")
2112 def generate_argument_parsing_code(self, env, code):
2113 # Generate PyArg_ParseTuple call for generic
2114 # arguments, if any.
2115 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
2116 # get rid of unused argument warning
2117 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
2119 old_error_label = code.new_error_label()
2120 our_error_label = code.error_label
2121 end_label = code.new_label("argument_unpacking_done")
2123 has_kwonly_args = self.num_kwonly_args > 0
2124 has_star_or_kw_args = self.star_arg is not None \
2125 or self.starstar_arg is not None or has_kwonly_args
2127 for arg in self.args:
2128 if not arg.type.is_pyobject:
2129 done = arg.type.create_from_py_utility_code(env)
2130 if not done: pass # will fail later
2132 if not self.signature_has_generic_args():
2133 if has_star_or_kw_args:
2134 error(self.pos, "This method cannot have * or keyword arguments")
2135 self.generate_argument_conversion_code(code)
2137 elif not self.signature_has_nongeneric_args():
2138 # func(*args) or func(**kw) or func(*args, **kw)
2139 self.generate_stararg_copy_code(code)
2141 else:
2142 positional_args = []
2143 kw_only_args = []
2144 for arg in self.args:
2145 arg_entry = arg.entry
2146 if arg.is_generic:
2147 if arg.default:
2148 if not arg.is_self_arg and not arg.is_type_arg:
2149 if arg.kw_only:
2150 kw_only_args.append(arg)
2151 else:
2152 positional_args.append(arg)
2153 elif arg.kw_only:
2154 kw_only_args.append(arg)
2155 elif not arg.is_self_arg and not arg.is_type_arg:
2156 positional_args.append(arg)
2158 self.generate_tuple_and_keyword_parsing_code(
2159 positional_args, kw_only_args, end_label, code)
2161 code.error_label = old_error_label
2162 if code.label_used(our_error_label):
2163 if not code.label_used(end_label):
2164 code.put_goto(end_label)
2165 code.put_label(our_error_label)
2166 if has_star_or_kw_args:
2167 self.generate_arg_decref(self.star_arg, code)
2168 if self.starstar_arg:
2169 if self.starstar_arg.entry.xdecref_cleanup:
2170 code.put_var_xdecref(self.starstar_arg.entry)
2171 else:
2172 code.put_var_decref(self.starstar_arg.entry)
2173 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2174 code.putln("return %s;" % self.error_value())
2175 if code.label_used(end_label):
2176 code.put_label(end_label)
2178 def generate_arg_assignment(self, arg, item, code):
2179 if arg.type.is_pyobject:
2180 if arg.is_generic:
2181 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2182 code.putln("%s = %s;" % (arg.entry.cname, item))
2183 else:
2184 func = arg.type.from_py_function
2185 if func:
2186 code.putln("%s = %s(%s); %s" % (
2187 arg.entry.cname,
2188 func,
2189 item,
2190 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2191 else:
2192 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2194 def generate_arg_xdecref(self, arg, code):
2195 if arg:
2196 code.put_var_xdecref(arg.entry)
2198 def generate_arg_decref(self, arg, code):
2199 if arg:
2200 code.put_var_decref(arg.entry)
2202 def generate_stararg_copy_code(self, code):
2203 if not self.star_arg:
2204 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2205 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2206 Naming.args_cname)
2207 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2208 self.name, Naming.args_cname, self.error_value()))
2209 code.putln("}")
2211 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2213 if self.starstar_arg:
2214 if self.star_arg:
2215 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2216 else:
2217 kwarg_check = "%s" % Naming.kwds_cname
2218 else:
2219 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2220 Naming.kwds_cname, Naming.kwds_cname)
2221 code.putln(
2222 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2223 kwarg_check, Naming.kwds_cname, self.name,
2224 bool(self.starstar_arg), self.error_value()))
2226 if self.starstar_arg:
2227 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2228 self.starstar_arg.entry.cname,
2229 Naming.kwds_cname,
2230 Naming.kwds_cname))
2231 code.putln("if (unlikely(!%s)) return %s;" % (
2232 self.starstar_arg.entry.cname, self.error_value()))
2233 self.starstar_arg.entry.xdecref_cleanup = 0
2234 code.put_gotref(self.starstar_arg.entry.cname)
2236 if self.self_in_stararg:
2237 # need to create a new tuple with 'self' inserted as first item
2238 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2239 self.star_arg.entry.cname,
2240 Naming.args_cname,
2241 self.star_arg.entry.cname))
2242 if self.starstar_arg:
2243 code.putln("{")
2244 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2245 code.putln("return %s;" % self.error_value())
2246 code.putln("}")
2247 else:
2248 code.putln("return %s;" % self.error_value())
2249 code.put_gotref(self.star_arg.entry.cname)
2250 code.put_incref(Naming.self_cname, py_object_type)
2251 code.put_giveref(Naming.self_cname)
2252 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2253 self.star_arg.entry.cname, Naming.self_cname))
2254 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2255 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2256 temp, temp, Naming.args_cname, temp))
2257 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2258 Naming.args_cname, temp))
2259 code.put_incref("item", py_object_type)
2260 code.put_giveref("item")
2261 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2262 self.star_arg.entry.cname, temp))
2263 code.putln("}")
2264 code.funcstate.release_temp(temp)
2265 self.star_arg.entry.xdecref_cleanup = 0
2266 elif self.star_arg:
2267 code.put_incref(Naming.args_cname, py_object_type)
2268 code.putln("%s = %s;" % (
2269 self.star_arg.entry.cname,
2270 Naming.args_cname))
2271 self.star_arg.entry.xdecref_cleanup = 0
2273 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2274 kw_only_args, success_label, code):
2275 argtuple_error_label = code.new_label("argtuple_error")
2277 min_positional_args = self.num_required_args - self.num_required_kw_args
2278 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2279 min_positional_args -= 1
2280 max_positional_args = len(positional_args)
2281 has_fixed_positional_count = not self.star_arg and \
2282 min_positional_args == max_positional_args
2284 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2285 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2286 if self.num_required_kw_args:
2287 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2289 if self.starstar_arg or self.star_arg:
2290 self.generate_stararg_init_code(max_positional_args, code)
2292 # --- optimised code when we receive keyword arguments
2293 if self.num_required_kw_args:
2294 likely_hint = "likely"
2295 else:
2296 likely_hint = "unlikely"
2297 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2298 self.generate_keyword_unpacking_code(
2299 min_positional_args, max_positional_args,
2300 has_fixed_positional_count,
2301 positional_args, kw_only_args, argtuple_error_label, code)
2303 # --- optimised code when we do not receive any keyword arguments
2304 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2305 # Python raises arg tuple related errors first, so we must
2306 # check the length here
2307 if min_positional_args == max_positional_args and not self.star_arg:
2308 compare = '!='
2309 else:
2310 compare = '<'
2311 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2312 Naming.args_cname, compare, min_positional_args))
2313 code.put_goto(argtuple_error_label)
2315 if self.num_required_kw_args:
2316 # pure error case: keywords required but not passed
2317 if max_positional_args > min_positional_args and not self.star_arg:
2318 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2319 Naming.args_cname, max_positional_args))
2320 code.put_goto(argtuple_error_label)
2321 code.putln('} else {')
2322 for i, arg in enumerate(kw_only_args):
2323 if not arg.default:
2324 pystring_cname = code.intern_identifier(arg.name)
2325 # required keyword-only argument missing
2326 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2327 self.name,
2328 pystring_cname))
2329 code.putln(code.error_goto(self.pos))
2330 break
2332 elif min_positional_args == max_positional_args:
2333 # parse the exact number of positional arguments from the
2334 # args tuple
2335 code.putln('} else {')
2336 for i, arg in enumerate(positional_args):
2337 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2338 self.generate_arg_assignment(arg, item, code)
2339 self.generate_arg_default_assignments(code)
2341 else:
2342 # parse the positional arguments from the variable length
2343 # args tuple
2344 code.putln('} else {')
2345 self.generate_arg_default_assignments(code)
2346 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2347 if self.star_arg:
2348 code.putln('default:')
2349 reversed_args = list(enumerate(positional_args))[::-1]
2350 for i, arg in reversed_args:
2351 if i >= min_positional_args-1:
2352 if min_positional_args > 1:
2353 code.putln('case %2d:' % (i+1)) # pure code beautification
2354 else:
2355 code.put('case %2d: ' % (i+1))
2356 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2357 self.generate_arg_assignment(arg, item, code)
2358 if min_positional_args == 0:
2359 code.put('case 0: ')
2360 code.putln('break;')
2361 if self.star_arg:
2362 if min_positional_args:
2363 for i in range(min_positional_args-1, -1, -1):
2364 code.putln('case %2d:' % i)
2365 code.put_goto(argtuple_error_label)
2366 else:
2367 code.put('default: ')
2368 code.put_goto(argtuple_error_label)
2369 code.putln('}')
2371 code.putln('}')
2373 if code.label_used(argtuple_error_label):
2374 code.put_goto(success_label)
2375 code.put_label(argtuple_error_label)
2376 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2377 self.name, has_fixed_positional_count,
2378 min_positional_args, max_positional_args,
2379 Naming.args_cname))
2380 code.putln(code.error_goto(self.pos))
2382 def generate_arg_default_assignments(self, code):
2383 for arg in self.args:
2384 if arg.is_generic and arg.default:
2385 code.putln(
2386 "%s = %s;" % (
2387 arg.entry.cname,
2388 arg.calculate_default_value_code(code)))
2390 def generate_stararg_init_code(self, max_positional_args, code):
2391 if self.starstar_arg:
2392 self.starstar_arg.entry.xdecref_cleanup = 0
2393 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2394 self.starstar_arg.entry.cname,
2395 self.starstar_arg.entry.cname,
2396 self.error_value()))
2397 code.put_gotref(self.starstar_arg.entry.cname)
2398 if self.star_arg:
2399 self.star_arg.entry.xdecref_cleanup = 0
2400 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2401 Naming.args_cname,
2402 max_positional_args))
2403 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2404 self.star_arg.entry.cname, Naming.args_cname,
2405 max_positional_args, Naming.args_cname))
2406 code.put_gotref(self.star_arg.entry.cname)
2407 if self.starstar_arg:
2408 code.putln("")
2409 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2410 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2411 code.putln('return %s;' % self.error_value())
2412 code.putln('}')
2413 else:
2414 code.putln("if (unlikely(!%s)) return %s;" % (
2415 self.star_arg.entry.cname, self.error_value()))
2416 code.putln('} else {')
2417 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2418 code.put_incref(Naming.empty_tuple, py_object_type)
2419 code.putln('}')
2421 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2422 has_fixed_positional_count, positional_args,
2423 kw_only_args, argtuple_error_label, code):
2424 all_args = tuple(positional_args) + tuple(kw_only_args)
2425 max_args = len(all_args)
2427 default_args = []
2428 for i, arg in enumerate(all_args):
2429 if arg.default and arg.type.is_pyobject:
2430 default_value = arg.calculate_default_value_code(code)
2431 if arg.type is not PyrexTypes.py_object_type:
2432 default_value = "(PyObject*)"+default_value
2433 default_args.append((i, default_value))
2435 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2436 Naming.kwds_cname)
2437 # it looks funny to separate the init-to-0 from setting the
2438 # default value, but C89 needs this
2439 code.putln("PyObject* values[%d] = {%s};" % (
2440 max_args, ','.join('0'*max_args)))
2441 for i, default_value in default_args:
2442 code.putln('values[%d] = %s;' % (i, default_value))
2444 # parse the tuple and check that it's not too long
2445 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2446 if self.star_arg:
2447 code.putln('default:')
2448 for i in range(max_positional_args-1, -1, -1):
2449 code.put('case %2d: ' % (i+1))
2450 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2451 i, Naming.args_cname, i))
2452 code.putln('case 0: break;')
2453 if not self.star_arg:
2454 code.put('default: ') # more arguments than allowed
2455 code.put_goto(argtuple_error_label)
2456 code.putln('}')
2458 # now fill up the positional/required arguments with values
2459 # from the kw dict
2460 if self.num_required_args or max_positional_args > 0:
2461 last_required_arg = -1
2462 for i, arg in enumerate(all_args):
2463 if not arg.default:
2464 last_required_arg = i
2465 if last_required_arg < max_positional_args:
2466 last_required_arg = max_positional_args-1
2467 num_required_args = self.num_required_args
2468 if max_positional_args > 0:
2469 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2470 for i, arg in enumerate(all_args[:last_required_arg+1]):
2471 if max_positional_args > 0 and i <= max_positional_args:
2472 if self.star_arg and i == max_positional_args:
2473 code.putln('default:')
2474 else:
2475 code.putln('case %2d:' % i)
2476 pystring_cname = code.intern_identifier(arg.name)
2477 if arg.default:
2478 if arg.kw_only:
2479 # handled separately below
2480 continue
2481 code.putln('if (kw_args > %d) {' % num_required_args)
2482 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2483 Naming.kwds_cname, pystring_cname))
2484 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2485 code.putln('}')
2486 else:
2487 num_required_args -= 1
2488 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2489 i, Naming.kwds_cname, pystring_cname))
2490 code.putln('if (likely(values[%d])) kw_args--;' % i);
2491 if i < min_positional_args:
2492 if i == 0:
2493 # special case: we know arg 0 is missing
2494 code.put('else ')
2495 code.put_goto(argtuple_error_label)
2496 else:
2497 # print the correct number of values (args or
2498 # kwargs) that were passed into positional
2499 # arguments up to this point
2500 code.putln('else {')
2501 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2502 self.name, has_fixed_positional_count,
2503 min_positional_args, max_positional_args, i))
2504 code.putln(code.error_goto(self.pos))
2505 code.putln('}')
2506 elif arg.kw_only:
2507 code.putln('else {')
2508 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2509 self.name, pystring_cname))
2510 code.putln(code.error_goto(self.pos))
2511 code.putln('}')
2512 if max_positional_args > 0:
2513 code.putln('}')
2515 if kw_only_args and not self.starstar_arg:
2516 # unpack optional keyword-only arguments
2517 # checking for interned strings in a dict is faster than iterating
2518 # but it's too likely that we must iterate if we expect **kwargs
2519 optional_args = []
2520 for i, arg in enumerate(all_args[max_positional_args:]):
2521 if not arg.kw_only or not arg.default:
2522 continue
2523 optional_args.append((i+max_positional_args, arg))
2524 if optional_args:
2525 # this mimics an unrolled loop so that we can "break" out of it
2526 code.putln('while (kw_args > 0) {')
2527 code.putln('PyObject* value;')
2528 for i, arg in optional_args:
2529 pystring_cname = code.intern_identifier(arg.name)
2530 code.putln(
2531 'value = PyDict_GetItem(%s, %s);' % (
2532 Naming.kwds_cname, pystring_cname))
2533 code.putln(
2534 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2535 code.putln('break;')
2536 code.putln('}')
2538 code.putln('if (unlikely(kw_args > 0)) {')
2539 # non-positional/-required kw args left in dict: default args,
2540 # kw-only args, **kwargs or error
2542 # This is sort of a catch-all: except for checking required
2543 # arguments, this will always do the right thing for unpacking
2544 # keyword arguments, so that we can concentrate on optimising
2545 # common cases above.
2546 if max_positional_args == 0:
2547 pos_arg_count = "0"
2548 elif self.star_arg:
2549 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2550 Naming.args_cname, max_positional_args,
2551 Naming.args_cname, max_positional_args))
2552 pos_arg_count = "used_pos_args"
2553 else:
2554 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2555 code.globalstate.use_utility_code(parse_keywords_utility_code)
2556 code.put(
2557 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2558 Naming.kwds_cname,
2559 Naming.pykwdlist_cname,
2560 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2561 pos_arg_count,
2562 self.name))
2563 code.putln(code.error_goto(self.pos))
2564 code.putln('}')
2566 # convert arg values to their final type and assign them
2567 for i, arg in enumerate(all_args):
2568 if arg.default and not arg.type.is_pyobject:
2569 code.putln("if (values[%d]) {" % i)
2570 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2571 if arg.default and not arg.type.is_pyobject:
2572 code.putln('} else {')
2573 code.putln(
2574 "%s = %s;" % (
2575 arg.entry.cname,
2576 arg.calculate_default_value_code(code)))
2577 code.putln('}')
2579 def generate_argument_conversion_code(self, code):
2580 # Generate code to convert arguments from
2581 # signature type to declared type, if needed.
2582 for arg in self.args:
2583 if arg.needs_conversion:
2584 self.generate_arg_conversion(arg, code)
2586 def generate_arg_conversion(self, arg, code):
2587 # Generate conversion code for one argument.
2588 old_type = arg.hdr_type
2589 new_type = arg.type
2590 if old_type.is_pyobject:
2591 if arg.default:
2592 code.putln("if (%s) {" % arg.hdr_cname)
2593 else:
2594 code.putln("assert(%s); {" % arg.hdr_cname)
2595 self.generate_arg_conversion_from_pyobject(arg, code)
2596 code.putln("}")
2597 elif new_type.is_pyobject:
2598 self.generate_arg_conversion_to_pyobject(arg, code)
2599 else:
2600 if new_type.assignable_from(old_type):
2601 code.putln(
2602 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2603 else:
2604 error(arg.pos,
2605 "Cannot convert 1 argument from '%s' to '%s'" %
2606 (old_type, new_type))
2608 def generate_arg_conversion_from_pyobject(self, arg, code):
2609 new_type = arg.type
2610 func = new_type.from_py_function
2611 # copied from CoerceFromPyTypeNode
2612 if func:
2613 code.putln("%s = %s(%s); %s" % (
2614 arg.entry.cname,
2615 func,
2616 arg.hdr_cname,
2617 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2618 else:
2619 error(arg.pos,
2620 "Cannot convert Python object argument to type '%s'"
2621 % new_type)
2623 def generate_arg_conversion_to_pyobject(self, arg, code):
2624 old_type = arg.hdr_type
2625 func = old_type.to_py_function
2626 if func:
2627 code.putln("%s = %s(%s); %s" % (
2628 arg.entry.cname,
2629 func,
2630 arg.hdr_cname,
2631 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2632 code.put_var_gotref(arg.entry)
2633 else:
2634 error(arg.pos,
2635 "Cannot convert argument of type '%s' to Python object"
2636 % old_type)
2638 def generate_argument_type_tests(self, code):
2639 # Generate type tests for args whose signature
2640 # type is PyObject * and whose declared type is
2641 # a subtype thereof.
2642 for arg in self.args:
2643 if arg.needs_type_test:
2644 self.generate_arg_type_test(arg, code)
2646 def generate_arg_type_test(self, arg, code):
2647 # Generate type test for one argument.
2648 if arg.type.typeobj_is_available():
2649 typeptr_cname = arg.type.typeptr_cname
2650 arg_code = "((PyObject *)%s)" % arg.entry.cname
2651 code.putln(
2652 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2653 arg_code,
2654 typeptr_cname,
2655 not arg.not_none,
2656 arg.name,
2657 arg.type.is_builtin_type,
2658 code.error_goto(arg.pos)))
2659 else:
2660 error(arg.pos, "Cannot test type of extern C class "
2661 "without type object name specification")
2663 def error_value(self):
2664 return self.entry.signature.error_value
2666 def caller_will_check_exceptions(self):
2667 return 1
2669 class OverrideCheckNode(StatNode):
2670 # A Node for dispatching to the def method if it
2671 # is overriden.
2673 # py_func
2675 # args
2676 # func_temp
2677 # body
2679 child_attrs = ['body']
2681 body = None
2683 def analyse_expressions(self, env):
2684 self.args = env.arg_entries
2685 if self.py_func.is_module_scope:
2686 first_arg = 0
2687 else:
2688 first_arg = 1
2689 import ExprNodes
2690 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2691 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2692 call_node = ExprNodes.SimpleCallNode(self.pos,
2693 function=self.func_node,
2694 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2695 self.body = ReturnStatNode(self.pos, value=call_node)
2696 self.body.analyse_expressions(env)
2698 def generate_execution_code(self, code):
2699 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2700 # Check to see if we are an extension type
2701 if self.py_func.is_module_scope:
2702 self_arg = "((PyObject *)%s)" % Naming.module_cname
2703 else:
2704 self_arg = "((PyObject *)%s)" % self.args[0].cname
2705 code.putln("/* Check if called by wrapper */")
2706 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2707 code.putln("/* Check if overriden in Python */")
2708 if self.py_func.is_module_scope:
2709 code.putln("else {")
2710 else:
2711 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2712 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2713 self.func_node.set_cname(func_node_temp)
2714 # need to get attribute manually--scope would return cdef method
2715 err = code.error_goto_if_null(func_node_temp, self.pos)
2716 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2717 func_node_temp, self_arg, interned_attr_cname, err))
2718 code.put_gotref(func_node_temp)
2719 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2720 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2721 func_node_temp, self.py_func.entry.func_cname)
2722 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2723 self.body.generate_execution_code(code)
2724 code.putln("}")
2725 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2726 code.funcstate.release_temp(func_node_temp)
2727 code.putln("}")
2729 class ClassDefNode(StatNode, BlockNode):
2730 pass
2732 class PyClassDefNode(ClassDefNode):
2733 # A Python class definition.
2735 # name EncodedString Name of the class
2736 # doc string or None
2737 # body StatNode Attribute definition code
2738 # entry Symtab.Entry
2739 # scope PyClassScope
2740 # decorators [DecoratorNode] list of decorators or None
2742 # The following subnodes are constructed internally:
2744 # dict DictNode Class dictionary
2745 # classobj ClassNode Class object
2746 # target NameNode Variable to assign class object to
2748 child_attrs = ["body", "dict", "classobj", "target"]
2749 decorators = None
2751 def __init__(self, pos, name, bases, doc, body, decorators = None):
2752 StatNode.__init__(self, pos)
2753 self.name = name
2754 self.doc = doc
2755 self.body = body
2756 self.decorators = decorators
2757 import ExprNodes
2758 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2759 if self.doc and Options.docstrings:
2760 doc = embed_position(self.pos, self.doc)
2761 # FIXME: correct string node?
2762 doc_node = ExprNodes.StringNode(pos, value = doc)
2763 else:
2764 doc_node = None
2765 self.classobj = ExprNodes.ClassNode(pos, name = name,
2766 bases = bases, dict = self.dict, doc = doc_node)
2767 self.target = ExprNodes.NameNode(pos, name = name)
2769 def as_cclass(self):
2770 """
2771 Return this node as if it were declared as an extension class
2772 """
2773 bases = self.classobj.bases.args
2774 if len(bases) == 0:
2775 base_class_name = None
2776 base_class_module = None
2777 elif len(bases) == 1:
2778 base = bases[0]
2779 path = []
2780 from ExprNodes import AttributeNode, NameNode
2781 while isinstance(base, AttributeNode):
2782 path.insert(0, base.attribute)
2783 base = base.obj
2784 if isinstance(base, NameNode):
2785 path.insert(0, base.name)
2786 base_class_name = path[-1]
2787 if len(path) > 1:
2788 base_class_module = u'.'.join(path[:-1])
2789 else:
2790 base_class_module = None
2791 else:
2792 error(self.classobj.bases.args.pos, "Invalid base class")
2793 else:
2794 error(self.classobj.bases.args.pos, "C class may only have one base class")
2795 return None
2797 return CClassDefNode(self.pos,
2798 visibility = 'private',
2799 module_name = None,
2800 class_name = self.name,
2801 base_class_module = base_class_module,
2802 base_class_name = base_class_name,
2803 decorators = self.decorators,
2804 body = self.body,
2805 in_pxd = False,
2806 doc = self.doc)
2808 def create_scope(self, env):
2809 genv = env
2810 while env.is_py_class_scope or env.is_c_class_scope:
2811 env = env.outer_scope
2812 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2813 return cenv
2815 def analyse_declarations(self, env):
2816 self.target.analyse_target_declaration(env)
2817 cenv = self.create_scope(env)
2818 cenv.directives = env.directives
2819 cenv.class_obj_cname = self.target.entry.cname
2820 self.body.analyse_declarations(cenv)
2822 def analyse_expressions(self, env):
2823 self.dict.analyse_expressions(env)
2824 self.classobj.analyse_expressions(env)
2825 genv = env.global_scope()
2826 cenv = self.scope
2827 self.body.analyse_expressions(cenv)
2828 self.target.analyse_target_expression(env, self.classobj)
2830 def generate_function_definitions(self, env, code):
2831 self.body.generate_function_definitions(self.scope, code)
2833 def generate_execution_code(self, code):
2834 code.pyclass_stack.append(self)
2835 cenv = self.scope
2836 self.dict.generate_evaluation_code(code)
2837 self.classobj.generate_evaluation_code(code)
2838 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2839 self.body.generate_execution_code(code)
2840 self.target.generate_assignment_code(self.classobj, code)
2841 self.dict.generate_disposal_code(code)
2842 self.dict.free_temps(code)
2843 code.pyclass_stack.pop()
2846 class CClassDefNode(ClassDefNode):
2847 # An extension type definition.
2849 # visibility 'private' or 'public' or 'extern'
2850 # typedef_flag boolean
2851 # api boolean
2852 # module_name string or None For import of extern type objects
2853 # class_name string Unqualified name of class
2854 # as_name string or None Name to declare as in this scope
2855 # base_class_module string or None Module containing the base class
2856 # base_class_name string or None Name of the base class
2857 # objstruct_name string or None Specified C name of object struct
2858 # typeobj_name string or None Specified C name of type object
2859 # in_pxd boolean Is in a .pxd file
2860 # decorators [DecoratorNode] list of decorators or None
2861 # doc string or None
2862 # body StatNode or None
2863 # entry Symtab.Entry
2864 # base_type PyExtensionType or None
2865 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2866 # buffer_defaults_pos
2868 child_attrs = ["body"]
2869 buffer_defaults_node = None
2870 buffer_defaults_pos = None
2871 typedef_flag = False
2872 api = False
2873 objstruct_name = None
2874 typeobj_name = None
2875 decorators = None
2877 def analyse_declarations(self, env):
2878 #print "CClassDefNode.analyse_declarations:", self.class_name
2879 #print "...visibility =", self.visibility
2880 #print "...module_name =", self.module_name
2882 import Buffer
2883 if self.buffer_defaults_node:
2884 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2885 env, [], self.buffer_defaults_node,
2886 need_complete=False)
2887 else:
2888 buffer_defaults = None
2890 if env.in_cinclude and not self.objstruct_name:
2891 error(self.pos, "Object struct name specification required for "
2892 "C class defined in 'extern from' block")
2893 self.base_type = None
2894 # Now that module imports are cached, we need to
2895 # import the modules for extern classes.
2896 if self.module_name:
2897 self.module = None
2898 for module in env.cimported_modules:
2899 if module.name == self.module_name:
2900 self.module = module
2901 if self.module is None:
2902 self.module = ModuleScope(self.module_name, None, env.context)
2903 self.module.has_extern_class = 1
2904 env.add_imported_module(self.module)
2906 if self.base_class_name:
2907 if self.base_class_module:
2908 base_class_scope = env.find_module(self.base_class_module, self.pos)
2909 else:
2910 base_class_scope = env
2911 if self.base_class_name == 'object':
2912 # extension classes are special and don't need to inherit from object
2913 if base_class_scope is None or base_class_scope.lookup('object') is None:
2914 self.base_class_name = None
2915 self.base_class_module = None
2916 base_class_scope = None
2917 if base_class_scope:
2918 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2919 if base_class_entry:
2920 if not base_class_entry.is_type:
2921 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2922 elif not base_class_entry.type.is_extension_type:
2923 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2924 elif not base_class_entry.type.is_complete():
2925 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2926 else:
2927 self.base_type = base_class_entry.type
2928 has_body = self.body is not None
2929 if self.module_name and self.visibility != 'extern':
2930 module_path = self.module_name.split(".")
2931 home_scope = env.find_imported_module(module_path, self.pos)
2932 if not home_scope:
2933 return
2934 else:
2935 home_scope = env
2937 if self.visibility == 'extern':
2938 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2939 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2941 self.entry = home_scope.declare_c_class(
2942 name = self.class_name,
2943 pos = self.pos,
2944 defining = has_body and self.in_pxd,
2945 implementing = has_body and not self.in_pxd,
2946 module_name = self.module_name,
2947 base_type = self.base_type,
2948 objstruct_cname = self.objstruct_name,
2949 typeobj_cname = self.typeobj_name,
2950 visibility = self.visibility,
2951 typedef_flag = self.typedef_flag,
2952 api = self.api,
2953 buffer_defaults = buffer_defaults)
2954 if home_scope is not env and self.visibility == 'extern':
2955 env.add_imported_entry(self.class_name, self.entry, pos)
2956 self.scope = scope = self.entry.type.scope
2957 if scope is not None:
2958 scope.directives = env.directives
2960 if self.doc and Options.docstrings:
2961 scope.doc = embed_position(self.pos, self.doc)
2963 if has_body:
2964 self.body.analyse_declarations(scope)
2965 if self.in_pxd:
2966 scope.defined = 1
2967 else:
2968 scope.implemented = 1
2969 env.allocate_vtable_names(self.entry)
2971 def analyse_expressions(self, env):
2972 if self.body:
2973 scope = self.entry.type.scope
2974 self.body.analyse_expressions(scope)
2976 def generate_function_definitions(self, env, code):
2977 if self.body:
2978 self.body.generate_function_definitions(
2979 self.entry.type.scope, code)
2981 def generate_execution_code(self, code):
2982 # This is needed to generate evaluation code for
2983 # default values of method arguments.
2984 if self.body:
2985 self.body.generate_execution_code(code)
2987 def annotate(self, code):
2988 if self.body:
2989 self.body.annotate(code)
2992 class PropertyNode(StatNode):
2993 # Definition of a property in an extension type.
2995 # name string
2996 # doc EncodedString or None Doc string
2997 # body StatListNode
2999 child_attrs = ["body"]
3001 def analyse_declarations(self, env):
3002 entry = env.declare_property(self.name, self.doc, self.pos)
3003 if entry:
3004 entry.scope.directives = env.directives
3005 self.body.analyse_declarations(entry.scope)
3007 def analyse_expressions(self, env):
3008 self.body.analyse_expressions(env)
3010 def generate_function_definitions(self, env, code):
3011 self.body.generate_function_definitions(env, code)
3013 def generate_execution_code(self, code):
3014 pass
3016 def annotate(self, code):
3017 self.body.annotate(code)
3020 class GlobalNode(StatNode):
3021 # Global variable declaration.
3023 # names [string]
3025 child_attrs = []
3027 def analyse_declarations(self, env):
3028 for name in self.names:
3029 env.declare_global(name, self.pos)
3031 def analyse_expressions(self, env):
3032 pass
3034 def generate_execution_code(self, code):
3035 pass
3038 class ExprStatNode(StatNode):
3039 # Expression used as a statement.
3041 # expr ExprNode
3043 child_attrs = ["expr"]
3045 def analyse_declarations(self, env):
3046 import ExprNodes
3047 if isinstance(self.expr, ExprNodes.GeneralCallNode):
3048 func = self.expr.function.as_cython_attribute()
3049 if func == u'declare':
3050 args, kwds = self.expr.explicit_args_kwds()
3051 if len(args):
3052 error(self.expr.pos, "Variable names must be specified.")
3053 for var, type_node in kwds.key_value_pairs:
3054 type = type_node.analyse_as_type(env)
3055 if type is None:
3056 error(type_node.pos, "Unknown type")
3057 else:
3058 env.declare_var(var.value, type, var.pos, is_cdef = True)
3059 self.__class__ = PassStatNode
3061 def analyse_expressions(self, env):
3062 self.expr.analyse_expressions(env)
3064 def generate_execution_code(self, code):
3065 self.expr.generate_evaluation_code(code)
3066 if not self.expr.is_temp and self.expr.result():
3067 code.putln("%s;" % self.expr.result())
3068 self.expr.generate_disposal_code(code)
3069 self.expr.free_temps(code)
3071 def annotate(self, code):
3072 self.expr.annotate(code)
3075 class AssignmentNode(StatNode):
3076 # Abstract base class for assignment nodes.
3078 # The analyse_expressions and generate_execution_code
3079 # phases of assignments are split into two sub-phases
3080 # each, to enable all the right hand sides of a
3081 # parallel assignment to be evaluated before assigning
3082 # to any of the left hand sides.
3084 def analyse_expressions(self, env):
3085 self.analyse_types(env)
3087 # def analyse_expressions(self, env):
3088 # self.analyse_expressions_1(env)
3089 # self.analyse_expressions_2(env)
3091 def generate_execution_code(self, code):
3092 self.generate_rhs_evaluation_code(code)
3093 self.generate_assignment_code(code)
3096 class SingleAssignmentNode(AssignmentNode):
3097 # The simplest case:
3099 # a = b
3101 # lhs ExprNode Left hand side
3102 # rhs ExprNode Right hand side
3103 # first bool Is this guaranteed the first assignment to lhs?
3105 child_attrs = ["lhs", "rhs"]
3106 first = False
3107 declaration_only = False
3109 def analyse_declarations(self, env):
3110 import ExprNodes
3112 # handle declarations of the form x = cython.foo()
3113 if isinstance(self.rhs, ExprNodes.CallNode):
3114 func_name = self.rhs.function.as_cython_attribute()
3115 if func_name:
3116 args, kwds = self.rhs.explicit_args_kwds()
3118 if func_name in ['declare', 'typedef']:
3119 if len(args) > 2 or kwds is not None:
3120 error(rhs.pos, "Can only declare one type at a time.")
3121 return
3122 type = args[0].analyse_as_type(env)
3123 if type is None:
3124 error(args[0].pos, "Unknown type")
3125 return
3126 lhs = self.lhs
3127 if func_name == 'declare':
3128 if isinstance(lhs, ExprNodes.NameNode):
3129 vars = [(lhs.name, lhs.pos)]
3130 elif isinstance(lhs, ExprNodes.TupleNode):
3131 vars = [(var.name, var.pos) for var in lhs.args]
3132 else:
3133 error(lhs.pos, "Invalid declaration")
3134 return
3135 for var, pos in vars:
3136 env.declare_var(var, type, pos, is_cdef = True)
3137 if len(args) == 2:
3138 # we have a value
3139 self.rhs = args[1]
3140 else:
3141 self.declaration_only = True
3142 else:
3143 self.declaration_only = True
3144 if not isinstance(lhs, ExprNodes.NameNode):
3145 error(lhs.pos, "Invalid declaration.")
3146 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3148 elif func_name in ['struct', 'union']:
3149 self.declaration_only = True
3150 if len(args) > 0 or kwds is None:
3151 error(rhs.pos, "Struct or union members must be given by name.")
3152 return
3153 members = []
3154 for member, type_node in kwds.key_value_pairs:
3155 type = type_node.analyse_as_type(env)
3156 if type is None:
3157 error(type_node.pos, "Unknown type")
3158 else:
3159 members.append((member.value, type, member.pos))
3160 if len(members) < len(kwds.key_value_pairs):
3161 return
3162 if not isinstance(self.lhs, ExprNodes.NameNode):
3163 error(self.lhs.pos, "Invalid declaration.")
3164 name = self.lhs.name
3165 scope = StructOrUnionScope(name)
3166 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3167 for member, type, pos in members:
3168 scope.declare_var(member, type, pos)
3170 if self.declaration_only:
3171 return
3172 else:
3173 self.lhs.analyse_target_declaration(env)
3175 def analyse_types(self, env, use_temp = 0):
3176 self.rhs.analyse_types(env)
3177 self.lhs.analyse_target_types(env)
3178 self.lhs.gil_assignment_check(env)
3179 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3180 if use_temp:
3181 self.rhs = self.rhs.coerce_to_temp(env)
3183 def generate_rhs_evaluation_code(self, code):
3184 self.rhs.generate_evaluation_code(code)
3186 def generate_assignment_code(self, code):
3187 self.lhs.generate_assignment_code(self.rhs, code)
3189 def annotate(self, code):
3190 self.lhs.annotate(code)
3191 self.rhs.annotate(code)
3194 class CascadedAssignmentNode(AssignmentNode):
3195 # An assignment with multiple left hand sides:
3197 # a = b = c
3199 # lhs_list [ExprNode] Left hand sides
3200 # rhs ExprNode Right hand sides
3202 # Used internally:
3204 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3206 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3207 coerced_rhs_list = None
3209 def analyse_declarations(self, env):
3210 for lhs in self.lhs_list:
3211 lhs.analyse_target_declaration(env)
3213 def analyse_types(self, env, use_temp = 0):
3214 self.rhs.analyse_types(env)
3215 if not self.rhs.is_simple():
3216 if use_temp:
3217 self.rhs = self.rhs.coerce_to_temp(env)
3218 else:
3219 self.rhs = self.rhs.coerce_to_simple(env)
3220 from ExprNodes import CloneNode
3221 self.coerced_rhs_list = []
3222 for lhs in self.lhs_list:
3223 lhs.analyse_target_types(env)
3224 lhs.gil_assignment_check(env)
3225 rhs = CloneNode(self.rhs)
3226 rhs = rhs.coerce_to(lhs.type, env)
3227 self.coerced_rhs_list.append(rhs)
3229 def generate_rhs_evaluation_code(self, code):
3230 self.rhs.generate_evaluation_code(code)
3232 def generate_assignment_code(self, code):
3233 for i in range(len(self.lhs_list)):
3234 lhs = self.lhs_list[i]
3235 rhs = self.coerced_rhs_list[i]
3236 rhs.generate_evaluation_code(code)
3237 lhs.generate_assignment_code(rhs, code)
3238 # Assignment has disposed of the cloned RHS
3239 self.rhs.generate_disposal_code(code)
3240 self.rhs.free_temps(code)
3242 def annotate(self, code):
3243 for i in range(len(self.lhs_list)):
3244 lhs = self.lhs_list[i].annotate(code)
3245 rhs = self.coerced_rhs_list[i].annotate(code)
3246 self.rhs.annotate(code)
3249 class ParallelAssignmentNode(AssignmentNode):
3250 # A combined packing/unpacking assignment:
3252 # a, b, c = d, e, f
3254 # This has been rearranged by the parser into
3256 # a = d ; b = e ; c = f
3258 # but we must evaluate all the right hand sides
3259 # before assigning to any of the left hand sides.
3261 # stats [AssignmentNode] The constituent assignments
3263 child_attrs = ["stats"]
3265 def analyse_declarations(self, env):
3266 for stat in self.stats:
3267 stat.analyse_declarations(env)
3269 def analyse_expressions(self, env):
3270 for stat in self.stats:
3271 stat.analyse_types(env, use_temp = 1)
3273 # def analyse_expressions(self, env):
3274 # for stat in self.stats:
3275 # stat.analyse_expressions_1(env, use_temp = 1)
3276 # for stat in self.stats:
3277 # stat.analyse_expressions_2(env)
3279 def generate_execution_code(self, code):
3280 for stat in self.stats:
3281 stat.generate_rhs_evaluation_code(code)
3282 for stat in self.stats:
3283 stat.generate_assignment_code(code)
3285 def annotate(self, code):
3286 for stat in self.stats:
3287 stat.annotate(code)
3290 class InPlaceAssignmentNode(AssignmentNode):
3291 # An in place arithmetic operand:
3293 # a += b
3294 # a -= b
3295 # ...
3297 # lhs ExprNode Left hand side
3298 # rhs ExprNode Right hand side
3299 # op char one of "+-*/%^&|"
3300 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3302 # This code is a bit tricky because in order to obey Python
3303 # semantics the sub-expressions (e.g. indices) of the lhs must
3304 # not be evaluated twice. So we must re-use the values calculated
3305 # in evaluation phase for the assignment phase as well.
3306 # Fortunately, the type of the lhs node is fairly constrained
3307 # (it must be a NameNode, AttributeNode, or IndexNode).
3309 child_attrs = ["lhs", "rhs"]
3310 dup = None
3312 def analyse_declarations(self, env):
3313 self.lhs.analyse_target_declaration(env)
3315 def analyse_types(self, env):
3316 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3317 self.rhs.analyse_types(env)
3318 self.lhs.analyse_target_types(env)
3319 import ExprNodes
3320 if self.lhs.type.is_pyobject:
3321 self.rhs = self.rhs.coerce_to_pyobject(env)
3322 elif self.rhs.type.is_pyobject:
3323 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3324 if self.lhs.type.is_pyobject:
3325 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3326 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3328 def generate_execution_code(self, code):
3329 import ExprNodes
3330 self.rhs.generate_evaluation_code(code)
3331 self.dup.generate_subexpr_evaluation_code(code)
3332 if self.dup.is_temp:
3333 self.dup.allocate_temp_result(code)
3334 # self.dup.generate_result_code is run only if it is not buffer access
3335 if self.operator == "**":
3336 extra = ", Py_None"
3337 else:
3338 extra = ""
3339 if self.lhs.type.is_pyobject:
3340 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3341 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3342 self.dup.generate_result_code(code)
3343 self.result_value_temp.allocate(code)
3344 code.putln(
3345 "%s = %s(%s, %s%s); %s" % (
3346 self.result_value.result(),
3347 self.py_operation_function(),
3348 self.dup.py_result(),
3349 self.rhs.py_result(),
3350 extra,
3351 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3352 code.put_gotref(self.result_value.py_result())
3353 self.result_value.generate_evaluation_code(code) # May be a type check...
3354 self.rhs.generate_disposal_code(code)
3355 self.rhs.free_temps(code)
3356 self.dup.generate_disposal_code(code)
3357 self.dup.free_temps(code)
3358 self.lhs.generate_assignment_code(self.result_value, code)
3359 self.result_value_temp.release(code)
3360 else:
3361 c_op = self.operator
3362 if c_op == "//":
3363 c_op = "/"
3364 elif c_op == "**":
3365 error(self.pos, "No C inplace power operator")
3366 elif self.lhs.type.is_complex:
3367 error(self.pos, "Inplace operators not implemented for complex types.")
3369 # have to do assignment directly to avoid side-effects
3370 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3371 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3372 else:
3373 self.dup.generate_result_code(code)
3374 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3375 self.rhs.generate_disposal_code(code)
3376 self.rhs.free_temps(code)
3377 if self.dup.is_temp:
3378 self.dup.generate_subexpr_disposal_code(code)
3379 self.dup.free_subexpr_temps(code)
3381 def create_dup_node(self, env):
3382 import ExprNodes
3383 self.dup = self.lhs
3384 self.dup.analyse_types(env)
3385 if isinstance(self.lhs, ExprNodes.NameNode):
3386 target_lhs = ExprNodes.NameNode(self.dup.pos,
3387 name = self.dup.name,
3388 is_temp = self.dup.is_temp,
3389 entry = self.dup.entry)
3390 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3391 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3392 obj = ExprNodes.CloneNode(self.lhs.obj),
3393 attribute = self.dup.attribute,
3394 is_temp = self.dup.is_temp)
3395 elif isinstance(self.lhs, ExprNodes.IndexNode):
3396 if self.lhs.index:
3397 index = ExprNodes.CloneNode(self.lhs.index)
3398 else:
3399 index = None
3400 if self.lhs.indices:
3401 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3402 else:
3403 indices = []
3404 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3405 base = ExprNodes.CloneNode(self.dup.base),
3406 index = index,
3407 indices = indices,
3408 is_temp = self.dup.is_temp)
3409 else:
3410 assert False
3411 self.lhs = target_lhs
3412 return self.dup
3414 def py_operation_function(self):
3415 return self.py_functions[self.operator]
3417 py_functions = {
3418 "|": "PyNumber_InPlaceOr",
3419 "^": "PyNumber_InPlaceXor",
3420 "&": "PyNumber_InPlaceAnd",
3421 "+": "PyNumber_InPlaceAdd",
3422 "-": "PyNumber_InPlaceSubtract",
3423 "*": "PyNumber_InPlaceMultiply",
3424 "/": "__Pyx_PyNumber_InPlaceDivide",
3425 "%": "PyNumber_InPlaceRemainder",
3426 "<<": "PyNumber_InPlaceLshift",
3427 ">>": "PyNumber_InPlaceRshift",
3428 "**": "PyNumber_InPlacePower",
3429 "//": "PyNumber_InPlaceFloorDivide",
3432 def annotate(self, code):
3433 self.lhs.annotate(code)
3434 self.rhs.annotate(code)
3435 self.dup.annotate(code)
3437 def create_binop_node(self):
3438 import ExprNodes
3439 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3442 class PrintStatNode(StatNode):
3443 # print statement
3445 # arg_tuple TupleNode
3446 # stream ExprNode or None (stdout)
3447 # append_newline boolean
3449 child_attrs = ["arg_tuple", "stream"]
3451 def analyse_expressions(self, env):
3452 if self.stream:
3453 self.stream.analyse_expressions(env)
3454 self.stream = self.stream.coerce_to_pyobject(env)
3455 self.arg_tuple.analyse_expressions(env)
3456 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3457 env.use_utility_code(printing_utility_code)
3458 if len(self.arg_tuple.args) == 1 and self.append_newline:
3459 env.use_utility_code(printing_one_utility_code)
3461 nogil_check = Node.gil_error
3462 gil_message = "Python print statement"
3464 def generate_execution_code(self, code):
3465 if self.stream:
3466 self.stream.generate_evaluation_code(code)
3467 stream_result = self.stream.py_result()
3468 else:
3469 stream_result = '0'
3470 if len(self.arg_tuple.args) == 1 and self.append_newline:
3471 arg = self.arg_tuple.args[0]
3472 arg.generate_evaluation_code(code)
3474 code.putln(
3475 "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
3476 stream_result,
3477 arg.py_result(),
3478 code.error_goto(self.pos)))
3479 arg.generate_disposal_code(code)
3480 arg.free_temps(code)
3481 else:
3482 self.arg_tuple.generate_evaluation_code(code)
3483 code.putln(
3484 "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
3485 stream_result,
3486 self.arg_tuple.py_result(),
3487 self.append_newline,
3488 code.error_goto(self.pos)))
3489 self.arg_tuple.generate_disposal_code(code)
3490 self.arg_tuple.free_temps(code)
3492 if self.stream:
3493 self.stream.generate_disposal_code(code)
3494 self.stream.free_temps(code)
3496 def annotate(self, code):
3497 if self.stream:
3498 self.stream.annotate(code)
3499 self.arg_tuple.annotate(code)
3502 class ExecStatNode(StatNode):
3503 # exec statement
3505 # args [ExprNode]
3507 child_attrs = ["args"]
3509 def analyse_expressions(self, env):
3510 for i, arg in enumerate(self.args):
3511 arg.analyse_expressions(env)
3512 arg = arg.coerce_to_pyobject(env)
3513 self.args[i] = arg
3514 env.use_utility_code(Builtin.pyexec_utility_code)
3516 nogil_check = Node.gil_error
3517 gil_message = "Python exec statement"
3519 def generate_execution_code(self, code):
3520 args = []
3521 for arg in self.args:
3522 arg.generate_evaluation_code(code)
3523 args.append( arg.py_result() )
3524 args = tuple(args + ['0', '0'][:3-len(args)])
3525 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3526 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3527 (temp_result,) + args))
3528 for arg in self.args:
3529 arg.generate_disposal_code(code)
3530 arg.free_temps(code)
3531 code.putln(
3532 code.error_goto_if_null(temp_result, self.pos))
3533 code.put_gotref(temp_result)
3534 code.put_decref_clear(temp_result, py_object_type)
3535 code.funcstate.release_temp(temp_result)
3537 def annotate(self, code):
3538 for arg in self.args:
3539 arg.annotate(code)
3542 class DelStatNode(StatNode):
3543 # del statement
3545 # args [ExprNode]
3547 child_attrs = ["args"]
3549 def analyse_declarations(self, env):
3550 for arg in self.args:
3551 arg.analyse_target_declaration(env)
3553 def analyse_expressions(self, env):
3554 for arg in self.args:
3555 arg.analyse_target_expression(env, None)
3556 if arg.type.is_pyobject:
3557 pass
3558 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3559 self.cpp_check(env)
3560 elif arg.type.is_cpp_class:
3561 error(arg.pos, "Deletion of non-heap C++ object")
3562 else:
3563 error(arg.pos, "Deletion of non-Python, non-C++ object")
3564 #arg.release_target_temp(env)
3566 def nogil_check(self, env):
3567 for arg in self.args:
3568 if arg.type.is_pyobject:
3569 self.gil_error()
3571 gil_message = "Deleting Python object"
3573 def generate_execution_code(self, code):
3574 for arg in self.args:
3575 if arg.type.is_pyobject:
3576 arg.generate_deletion_code(code)
3577 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3578 arg.generate_result_code(code)
3579 code.putln("delete %s;" % arg.result())
3580 # else error reported earlier
3582 def annotate(self, code):
3583 for arg in self.args:
3584 arg.annotate(code)
3587 class PassStatNode(StatNode):
3588 # pass statement
3590 child_attrs = []
3592 def analyse_expressions(self, env):
3593 pass
3595 def generate_execution_code(self, code):
3596 pass
3599 class BreakStatNode(StatNode):
3601 child_attrs = []
3603 def analyse_expressions(self, env):
3604 pass
3606 def generate_execution_code(self, code):
3607 if not code.break_label:
3608 error(self.pos, "break statement not inside loop")
3609 else:
3610 code.put_goto(code.break_label)
3613 class ContinueStatNode(StatNode):
3615 child_attrs = []
3617 def analyse_expressions(self, env):
3618 pass
3620 def generate_execution_code(self, code):
3621 if code.funcstate.in_try_finally:
3622 error(self.pos, "continue statement inside try of try...finally")
3623 elif not code.continue_label:
3624 error(self.pos, "continue statement not inside loop")
3625 else:
3626 code.put_goto(code.continue_label)
3629 class ReturnStatNode(StatNode):
3630 # return statement
3632 # value ExprNode or None
3633 # return_type PyrexType
3635 child_attrs = ["value"]
3637 def analyse_expressions(self, env):
3638 return_type = env.return_type
3639 self.return_type = return_type
3640 if not return_type:
3641 error(self.pos, "Return not inside a function body")
3642 return
3643 if self.value:
3644 self.value.analyse_types(env)
3645 if return_type.is_void or return_type.is_returncode:
3646 error(self.value.pos,
3647 "Return with value in void function")
3648 else:
3649 self.value = self.value.coerce_to(env.return_type, env)
3650 else:
3651 if (not return_type.is_void
3652 and not return_type.is_pyobject
3653 and not return_type.is_returncode):
3654 error(self.pos, "Return value required")
3656 def nogil_check(self, env):
3657 if self.return_type.is_pyobject:
3658 self.gil_error()
3660 gil_message = "Returning Python object"
3662 def generate_execution_code(self, code):
3663 code.mark_pos(self.pos)
3664 if not self.return_type:
3665 # error reported earlier
3666 return
3667 if self.return_type.is_pyobject:
3668 code.put_xdecref(Naming.retval_cname,
3669 self.return_type)
3670 if self.value:
3671 self.value.generate_evaluation_code(code)
3672 self.value.make_owned_reference(code)
3673 code.putln(
3674 "%s = %s;" % (
3675 Naming.retval_cname,
3676 self.value.result_as(self.return_type)))
3677 self.value.generate_post_assignment_code(code)
3678 self.value.free_temps(code)
3679 else:
3680 if self.return_type.is_pyobject:
3681 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3682 elif self.return_type.is_returncode:
3683 code.putln(
3684 "%s = %s;" % (
3685 Naming.retval_cname,
3686 self.return_type.default_value))
3687 for cname, type in code.funcstate.temps_holding_reference():
3688 code.put_decref_clear(cname, type)
3689 code.put_goto(code.return_label)
3691 def annotate(self, code):
3692 if self.value:
3693 self.value.annotate(code)
3696 class RaiseStatNode(StatNode):
3697 # raise statement
3699 # exc_type ExprNode or None
3700 # exc_value ExprNode or None
3701 # exc_tb ExprNode or None
3703 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3705 def analyse_expressions(self, env):
3706 if self.exc_type:
3707 self.exc_type.analyse_types(env)
3708 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3709 if self.exc_value:
3710 self.exc_value.analyse_types(env)
3711 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3712 if self.exc_tb:
3713 self.exc_tb.analyse_types(env)
3714 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3715 env.use_utility_code(raise_utility_code)
3717 nogil_check = Node.gil_error
3718 gil_message = "Raising exception"
3720 def generate_execution_code(self, code):
3721 if self.exc_type:
3722 self.exc_type.generate_evaluation_code(code)
3723 type_code = self.exc_type.py_result()
3724 else:
3725 type_code = "0"
3726 if self.exc_value:
3727 self.exc_value.generate_evaluation_code(code)
3728 value_code = self.exc_value.py_result()
3729 else:
3730 value_code = "0"
3731 if self.exc_tb:
3732 self.exc_tb.generate_evaluation_code(code)
3733 tb_code = self.exc_tb.py_result()
3734 else:
3735 tb_code = "0"
3736 code.putln(
3737 "__Pyx_Raise(%s, %s, %s);" % (
3738 type_code,
3739 value_code,
3740 tb_code))
3741 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3742 if obj:
3743 obj.generate_disposal_code(code)
3744 obj.free_temps(code)
3745 code.putln(
3746 code.error_goto(self.pos))
3748 def annotate(self, code):
3749 if self.exc_type:
3750 self.exc_type.annotate(code)
3751 if self.exc_value:
3752 self.exc_value.annotate(code)
3753 if self.exc_tb:
3754 self.exc_tb.annotate(code)
3757 class ReraiseStatNode(StatNode):
3759 child_attrs = []
3761 def analyse_expressions(self, env):
3762 env.use_utility_code(restore_exception_utility_code)
3764 nogil_check = Node.gil_error
3765 gil_message = "Raising exception"
3767 def generate_execution_code(self, code):
3768 vars = code.funcstate.exc_vars
3769 if vars:
3770 for varname in vars:
3771 code.put_giveref(varname)
3772 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3773 for varname in vars:
3774 code.put("%s = 0; " % varname)
3775 code.putln()
3776 code.putln(code.error_goto(self.pos))
3777 else:
3778 error(self.pos, "Reraise not inside except clause")
3781 class AssertStatNode(StatNode):
3782 # assert statement
3784 # cond ExprNode
3785 # value ExprNode or None
3787 child_attrs = ["cond", "value"]
3789 def analyse_expressions(self, env):
3790 self.cond = self.cond.analyse_boolean_expression(env)
3791 if self.value:
3792 self.value.analyse_types(env)
3793 self.value = self.value.coerce_to_pyobject(env)
3795 nogil_check = Node.gil_error
3796 gil_message = "Raising exception"
3798 def generate_execution_code(self, code):
3799 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3800 self.cond.generate_evaluation_code(code)
3801 code.putln(
3802 "if (unlikely(!%s)) {" %
3803 self.cond.result())
3804 if self.value:
3805 self.value.generate_evaluation_code(code)
3806 code.putln(
3807 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3808 self.value.py_result())
3809 self.value.generate_disposal_code(code)
3810 self.value.free_temps(code)
3811 else:
3812 code.putln(
3813 "PyErr_SetNone(PyExc_AssertionError);")
3814 code.putln(
3815 code.error_goto(self.pos))
3816 code.putln(
3817 "}")
3818 self.cond.generate_disposal_code(code)
3819 self.cond.free_temps(code)
3820 code.putln("#endif")
3822 def annotate(self, code):
3823 self.cond.annotate(code)
3824 if self.value:
3825 self.value.annotate(code)
3828 class IfStatNode(StatNode):
3829 # if statement
3831 # if_clauses [IfClauseNode]
3832 # else_clause StatNode or None
3834 child_attrs = ["if_clauses", "else_clause"]
3836 def analyse_control_flow(self, env):
3837 env.start_branching(self.pos)
3838 for if_clause in self.if_clauses:
3839 if_clause.analyse_control_flow(env)
3840 env.next_branch(if_clause.end_pos())
3841 if self.else_clause:
3842 self.else_clause.analyse_control_flow(env)
3843 env.finish_branching(self.end_pos())
3845 def analyse_declarations(self, env):
3846 for if_clause in self.if_clauses:
3847 if_clause.analyse_declarations(env)
3848 if self.else_clause:
3849 self.else_clause.analyse_declarations(env)
3851 def analyse_expressions(self, env):
3852 for if_clause in self.if_clauses:
3853 if_clause.analyse_expressions(env)
3854 if self.else_clause:
3855 self.else_clause.analyse_expressions(env)
3857 def generate_execution_code(self, code):
3858 code.mark_pos(self.pos)
3859 end_label = code.new_label()
3860 for if_clause in self.if_clauses:
3861 if_clause.generate_execution_code(code, end_label)
3862 if self.else_clause:
3863 code.putln("/*else*/ {")
3864 self.else_clause.generate_execution_code(code)
3865 code.putln("}")
3866 code.put_label(end_label)
3868 def annotate(self, code):
3869 for if_clause in self.if_clauses:
3870 if_clause.annotate(code)
3871 if self.else_clause:
3872 self.else_clause.annotate(code)
3875 class IfClauseNode(Node):
3876 # if or elif clause in an if statement
3878 # condition ExprNode
3879 # body StatNode
3881 child_attrs = ["condition", "body"]
3883 def analyse_control_flow(self, env):
3884 self.body.analyse_control_flow(env)
3886 def analyse_declarations(self, env):
3887 self.condition.analyse_declarations(env)
3888 self.body.analyse_declarations(env)
3890 def analyse_expressions(self, env):
3891 self.condition = \
3892 self.condition.analyse_temp_boolean_expression(env)
3893 self.body.analyse_expressions(env)
3895 def generate_execution_code(self, code, end_label):
3896 self.condition.generate_evaluation_code(code)
3897 code.putln(
3898 "if (%s) {" %
3899 self.condition.result())
3900 self.condition.generate_disposal_code(code)
3901 self.condition.free_temps(code)
3902 self.body.generate_execution_code(code)
3903 code.put_goto(end_label)
3904 code.putln("}")
3906 def annotate(self, code):
3907 self.condition.annotate(code)
3908 self.body.annotate(code)
3911 class SwitchCaseNode(StatNode):
3912 # Generated in the optimization of an if-elif-else node
3914 # conditions [ExprNode]
3915 # body StatNode
3917 child_attrs = ['conditions', 'body']
3919 def generate_execution_code(self, code):
3920 for cond in self.conditions:
3921 code.mark_pos(cond.pos)
3922 cond.generate_evaluation_code(code)
3923 code.putln("case %s:" % cond.result())
3924 self.body.generate_execution_code(code)
3925 code.putln("break;")
3927 def annotate(self, code):
3928 for cond in self.conditions:
3929 cond.annotate(code)
3930 self.body.annotate(code)
3932 class SwitchStatNode(StatNode):
3933 # Generated in the optimization of an if-elif-else node
3935 # test ExprNode
3936 # cases [SwitchCaseNode]
3937 # else_clause StatNode or None
3939 child_attrs = ['test', 'cases', 'else_clause']
3941 def generate_execution_code(self, code):
3942 code.putln("switch (%s) {" % self.test.result())
3943 for case in self.cases:
3944 case.generate_execution_code(code)
3945 if self.else_clause is not None:
3946 code.putln("default:")
3947 self.else_clause.generate_execution_code(code)
3948 code.putln("break;")
3949 code.putln("}")
3951 def annotate(self, code):
3952 self.test.annotate(code)
3953 for case in self.cases:
3954 case.annotate(code)
3955 if self.else_clause is not None:
3956 self.else_clause.annotate(code)
3958 class LoopNode(object):
3960 def analyse_control_flow(self, env):
3961 env.start_branching(self.pos)
3962 self.body.analyse_control_flow(env)
3963 env.next_branch(self.body.end_pos())
3964 if self.else_clause:
3965 self.else_clause.analyse_control_flow(env)
3966 env.finish_branching(self.end_pos())
3969 class WhileStatNode(LoopNode, StatNode):
3970 # while statement
3972 # condition ExprNode
3973 # body StatNode
3974 # else_clause StatNode
3976 child_attrs = ["condition", "body", "else_clause"]
3978 def analyse_declarations(self, env):
3979 self.body.analyse_declarations(env)
3980 if self.else_clause:
3981 self.else_clause.analyse_declarations(env)
3983 def analyse_expressions(self, env):
3984 self.condition = \
3985 self.condition.analyse_temp_boolean_expression(env)
3986 self.body.analyse_expressions(env)
3987 if self.else_clause:
3988 self.else_clause.analyse_expressions(env)
3990 def generate_execution_code(self, code):
3991 old_loop_labels = code.new_loop_labels()
3992 code.putln(
3993 "while (1) {")
3994 self.condition.generate_evaluation_code(code)
3995 self.condition.generate_disposal_code(code)
3996 code.putln(
3997 "if (!%s) break;" %
3998 self.condition.result())
3999 self.condition.free_temps(code)
4000 self.body.generate_execution_code(code)
4001 code.put_label(code.continue_label)
4002 code.putln("}")
4003 break_label = code.break_label
4004 code.set_loop_labels(old_loop_labels)
4005 if self.else_clause:
4006 code.putln("/*else*/ {")
4007 self.else_clause.generate_execution_code(code)
4008 code.putln("}")
4009 code.put_label(break_label)
4011 def annotate(self, code):
4012 self.condition.annotate(code)
4013 self.body.annotate(code)
4014 if self.else_clause:
4015 self.else_clause.annotate(code)
4018 def ForStatNode(pos, **kw):
4019 if 'iterator' in kw:
4020 return ForInStatNode(pos, **kw)
4021 else:
4022 return ForFromStatNode(pos, **kw)
4024 class ForInStatNode(LoopNode, StatNode):
4025 # for statement
4027 # target ExprNode
4028 # iterator IteratorNode
4029 # body StatNode
4030 # else_clause StatNode
4031 # item NextNode used internally
4033 child_attrs = ["target", "iterator", "body", "else_clause"]
4034 item = None
4036 def analyse_declarations(self, env):
4037 self.target.analyse_target_declaration(env)
4038 self.body.analyse_declarations(env)
4039 if self.else_clause:
4040 self.else_clause.analyse_declarations(env)
4042 def analyse_expressions(self, env):
4043 import ExprNodes
4044 self.target.analyse_target_types(env)
4045 self.iterator.analyse_expressions(env)
4046 self.item = ExprNodes.NextNode(self.iterator, env)
4047 self.item = self.item.coerce_to(self.target.type, env)
4048 self.body.analyse_expressions(env)
4049 if self.else_clause:
4050 self.else_clause.analyse_expressions(env)
4052 def generate_execution_code(self, code):
4053 old_loop_labels = code.new_loop_labels()
4054 self.iterator.allocate_counter_temp(code)
4055 self.iterator.generate_evaluation_code(code)
4056 code.putln(
4057 "for (;;) {")
4058 self.item.generate_evaluation_code(code)
4059 self.target.generate_assignment_code(self.item, code)
4060 self.body.generate_execution_code(code)
4061 code.put_label(code.continue_label)
4062 code.putln(
4063 "}")
4064 break_label = code.break_label
4065 code.set_loop_labels(old_loop_labels)
4066 if self.else_clause:
4067 code.putln("/*else*/ {")
4068 self.else_clause.generate_execution_code(code)
4069 code.putln("}")
4070 code.put_label(break_label)
4071 self.iterator.release_counter_temp(code)
4072 self.iterator.generate_disposal_code(code)
4073 self.iterator.free_temps(code)
4075 def annotate(self, code):
4076 self.target.annotate(code)
4077 self.iterator.annotate(code)
4078 self.body.annotate(code)
4079 if self.else_clause:
4080 self.else_clause.annotate(code)
4081 self.item.annotate(code)
4084 class ForFromStatNode(LoopNode, StatNode):
4085 # for name from expr rel name rel expr
4087 # target NameNode
4088 # bound1 ExprNode
4089 # relation1 string
4090 # relation2 string
4091 # bound2 ExprNode
4092 # step ExprNode or None
4093 # body StatNode
4094 # else_clause StatNode or None
4096 # Used internally:
4098 # from_range bool
4099 # is_py_target bool
4100 # loopvar_node ExprNode (usually a NameNode or temp node)
4101 # py_loopvar_node PyTempNode or None
4102 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
4104 is_py_target = False
4105 loopvar_node = None
4106 py_loopvar_node = None
4107 from_range = False
4109 gil_message = "For-loop using object bounds or target"
4111 def nogil_check(self, env):
4112 for x in (self.target, self.bound1, self.bound2):
4113 if x.type.is_pyobject:
4114 self.gil_error()
4116 def analyse_declarations(self, env):
4117 self.target.analyse_target_declaration(env)
4118 self.body.analyse_declarations(env)
4119 if self.else_clause:
4120 self.else_clause.analyse_declarations(env)
4122 def analyse_expressions(self, env):
4123 import ExprNodes
4124 self.target.analyse_target_types(env)
4125 self.bound1.analyse_types(env)
4126 self.bound2.analyse_types(env)
4127 if self.step is not None:
4128 if isinstance(self.step, ExprNodes.UnaryMinusNode):
4129 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
4130 self.step.analyse_types(env)
4132 target_type = self.target.type
4133 if self.target.type.is_numeric:
4134 loop_type = self.target.type
4135 else:
4136 loop_type = PyrexTypes.c_int_type
4137 if not self.bound1.type.is_pyobject:
4138 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
4139 if not self.bound2.type.is_pyobject:
4140 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
4141 if self.step is not None and not self.step.type.is_pyobject:
4142 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
4143 self.bound1 = self.bound1.coerce_to(loop_type, env)
4144 self.bound2 = self.bound2.coerce_to(loop_type, env)
4145 if not self.bound2.is_literal:
4146 self.bound2 = self.bound2.coerce_to_temp(env)
4147 if self.step is not None:
4148 self.step = self.step.coerce_to(loop_type, env)
4149 if not self.step.is_literal:
4150 self.step = self.step.coerce_to_temp(env)
4152 target_type = self.target.type
4153 if not (target_type.is_pyobject or target_type.is_numeric):
4154 error(self.target.pos,
4155 "for-from loop variable must be c numeric type or Python object")
4156 if target_type.is_numeric:
4157 self.is_py_target = False
4158 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
4159 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
4160 self.loopvar_node = self.target
4161 self.py_loopvar_node = None
4162 else:
4163 self.is_py_target = True
4164 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
4165 self.loopvar_node = c_loopvar_node
4166 self.py_loopvar_node = \
4167 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
4168 self.body.analyse_expressions(env)
4169 if self.else_clause:
4170 self.else_clause.analyse_expressions(env)
4172 def generate_execution_code(self, code):
4173 old_loop_labels = code.new_loop_labels()
4174 from_range = self.from_range
4175 self.bound1.generate_evaluation_code(code)
4176 self.bound2.generate_evaluation_code(code)
4177 offset, incop = self.relation_table[self.relation1]
4178 if self.step is not None:
4179 self.step.generate_evaluation_code(code)
4180 step = self.step.result()
4181 incop = "%s=%s" % (incop[0], step)
4182 import ExprNodes
4183 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4184 self.loopvar_node.allocate(code)
4185 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4186 self.py_loopvar_node.allocate(code)
4187 if from_range:
4188 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4189 else:
4190 loopvar_name = self.loopvar_node.result()
4191 code.putln(
4192 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4193 loopvar_name,
4194 self.bound1.result(), offset,
4195 loopvar_name, self.relation2, self.bound2.result(),
4196 loopvar_name, incop))
4197 if self.py_loopvar_node:
4198 self.py_loopvar_node.generate_evaluation_code(code)
4199 self.target.generate_assignment_code(self.py_loopvar_node, code)
4200 elif from_range:
4201 code.putln("%s = %s;" % (
4202 self.target.result(), loopvar_name))
4203 self.body.generate_execution_code(code)
4204 code.put_label(code.continue_label)
4205 if self.py_loopvar_node:
4206 # This mess is to make for..from loops with python targets behave
4207 # exactly like those with C targets with regards to re-assignment
4208 # of the loop variable.
4209 import ExprNodes
4210 if self.target.entry.is_pyglobal:
4211 # We know target is a NameNode, this is the only ugly case.
4212 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4213 target_node.allocate(code)
4214 interned_cname = code.intern_identifier(self.target.entry.name)
4215 code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
4216 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4217 target_node.result(),
4218 Naming.module_cname,
4219 interned_cname,
4220 code.error_goto_if_null(target_node.result(), self.target.pos)))
4221 code.put_gotref(target_node.result())
4222 else:
4223 target_node = self.target
4224 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4225 from_py_node.temp_code = loopvar_name
4226 from_py_node.generate_result_code(code)
4227 if self.target.entry.is_pyglobal:
4228 code.put_decref(target_node.result(), target_node.type)
4229 target_node.release(code)
4230 code.putln("}")
4231 if self.py_loopvar_node:
4232 # This is potentially wasteful, but we don't want the semantics to
4233 # depend on whether or not the loop is a python type.
4234 self.py_loopvar_node.generate_evaluation_code(code)
4235 self.target.generate_assignment_code(self.py_loopvar_node, code)
4236 if from_range:
4237 code.funcstate.release_temp(loopvar_name)
4238 break_label = code.break_label
4239 code.set_loop_labels(old_loop_labels)
4240 if self.else_clause:
4241 code.putln("/*else*/ {")
4242 self.else_clause.generate_execution_code(code)
4243 code.putln("}")
4244 code.put_label(break_label)
4245 self.bound1.generate_disposal_code(code)
4246 self.bound1.free_temps(code)
4247 self.bound2.generate_disposal_code(code)
4248 self.bound2.free_temps(code)
4249 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4250 self.loopvar_node.release(code)
4251 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4252 self.py_loopvar_node.release(code)
4253 if self.step is not None:
4254 self.step.generate_disposal_code(code)
4255 self.step.free_temps(code)
4257 relation_table = {
4258 # {relop : (initial offset, increment op)}
4259 '<=': ("", "++"),
4260 '<' : ("+1", "++"),
4261 '>=': ("", "--"),
4262 '>' : ("-1", "--")
4265 def annotate(self, code):
4266 self.target.annotate(code)
4267 self.bound1.annotate(code)
4268 self.bound2.annotate(code)
4269 if self.step:
4270 self.bound2.annotate(code)
4271 self.body.annotate(code)
4272 if self.else_clause:
4273 self.else_clause.annotate(code)
4276 class WithStatNode(StatNode):
4277 """
4278 Represents a Python with statement.
4280 This is only used at parse tree level; and is not present in
4281 analysis or generation phases.
4282 """
4283 # manager The with statement manager object
4284 # target Node (lhs expression)
4285 # body StatNode
4286 child_attrs = ["manager", "target", "body"]
4288 class TryExceptStatNode(StatNode):
4289 # try .. except statement
4291 # body StatNode
4292 # except_clauses [ExceptClauseNode]
4293 # else_clause StatNode or None
4295 child_attrs = ["body", "except_clauses", "else_clause"]
4297 def analyse_control_flow(self, env):
4298 env.start_branching(self.pos)
4299 self.body.analyse_control_flow(env)
4300 successful_try = env.control_flow # grab this for later
4301 env.next_branch(self.body.end_pos())
4302 env.finish_branching(self.body.end_pos())
4304 env.start_branching(self.except_clauses[0].pos)
4305 for except_clause in self.except_clauses:
4306 except_clause.analyse_control_flow(env)
4307 env.next_branch(except_clause.end_pos())
4309 # the else cause it executed only when the try clause finishes
4310 env.control_flow.incoming = successful_try
4311 if self.else_clause:
4312 self.else_clause.analyse_control_flow(env)
4313 env.finish_branching(self.end_pos())
4315 def analyse_declarations(self, env):
4316 self.body.analyse_declarations(env)
4317 for except_clause in self.except_clauses:
4318 except_clause.analyse_declarations(env)
4319 if self.else_clause:
4320 self.else_clause.analyse_declarations(env)
4321 env.use_utility_code(reset_exception_utility_code)
4323 def analyse_expressions(self, env):
4324 self.body.analyse_expressions(env)
4325 default_clause_seen = 0
4326 for except_clause in self.except_clauses:
4327 except_clause.analyse_expressions(env)
4328 if default_clause_seen:
4329 error(except_clause.pos, "default 'except:' must be last")
4330 if not except_clause.pattern:
4331 default_clause_seen = 1
4332 self.has_default_clause = default_clause_seen
4333 if self.else_clause:
4334 self.else_clause.analyse_expressions(env)
4336 nogil_check = Node.gil_error
4337 gil_message = "Try-except statement"
4339 def generate_execution_code(self, code):
4340 old_return_label = code.return_label
4341 old_break_label = code.break_label
4342 old_continue_label = code.continue_label
4343 old_error_label = code.new_error_label()
4344 our_error_label = code.error_label
4345 except_end_label = code.new_label('exception_handled')
4346 except_error_label = code.new_label('except_error')
4347 except_return_label = code.new_label('except_return')
4348 try_return_label = code.new_label('try_return')
4349 try_break_label = code.new_label('try_break')
4350 try_continue_label = code.new_label('try_continue')
4351 try_end_label = code.new_label('try_end')
4353 code.putln("{")
4354 code.putln("PyObject %s;" %
4355 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4356 code.putln("__Pyx_ExceptionSave(%s);" %
4357 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4358 for var in Naming.exc_save_vars:
4359 code.put_xgotref(var)
4360 code.putln(
4361 "/*try:*/ {")
4362 code.return_label = try_return_label
4363 code.break_label = try_break_label
4364 code.continue_label = try_continue_label
4365 self.body.generate_execution_code(code)
4366 code.putln(
4367 "}")
4368 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4369 code.error_label = except_error_label
4370 code.return_label = except_return_label
4371 if self.else_clause:
4372 code.putln(
4373 "/*else:*/ {")
4374 self.else_clause.generate_execution_code(code)
4375 code.putln(
4376 "}")
4377 for var in Naming.exc_save_vars:
4378 code.put_xdecref_clear(var, py_object_type)
4379 code.put_goto(try_end_label)
4380 if code.label_used(try_return_label):
4381 code.put_label(try_return_label)
4382 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4383 code.putln("__Pyx_ExceptionReset(%s);" %
4384 ', '.join(Naming.exc_save_vars))
4385 code.put_goto(old_return_label)
4386 code.put_label(our_error_label)
4387 for temp_name, type in temps_to_clean_up:
4388 code.put_xdecref_clear(temp_name, type)
4389 for except_clause in self.except_clauses:
4390 except_clause.generate_handling_code(code, except_end_label)
4392 error_label_used = code.label_used(except_error_label)
4393 if error_label_used or not self.has_default_clause:
4394 if error_label_used:
4395 code.put_label(except_error_label)
4396 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4397 code.putln("__Pyx_ExceptionReset(%s);" %
4398 ', '.join(Naming.exc_save_vars))
4399 code.put_goto(old_error_label)
4401 for exit_label, old_label in zip(
4402 [try_break_label, try_continue_label, except_return_label],
4403 [old_break_label, old_continue_label, old_return_label]):
4405 if code.label_used(exit_label):
4406 code.put_label(exit_label)
4407 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4408 code.putln("__Pyx_ExceptionReset(%s);" %
4409 ', '.join(Naming.exc_save_vars))
4410 code.put_goto(old_label)
4412 if code.label_used(except_end_label):
4413 code.put_label(except_end_label)
4414 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4415 code.putln("__Pyx_ExceptionReset(%s);" %
4416 ', '.join(Naming.exc_save_vars))
4417 code.put_label(try_end_label)
4418 code.putln("}")
4420 code.return_label = old_return_label
4421 code.break_label = old_break_label
4422 code.continue_label = old_continue_label
4423 code.error_label = old_error_label
4425 def annotate(self, code):
4426 self.body.annotate(code)
4427 for except_node in self.except_clauses:
4428 except_node.annotate(code)
4429 if self.else_clause:
4430 self.else_clause.annotate(code)
4433 class ExceptClauseNode(Node):
4434 # Part of try ... except statement.
4436 # pattern ExprNode
4437 # target ExprNode or None
4438 # body StatNode
4439 # excinfo_target NameNode or None optional target for exception info
4440 # match_flag string result of exception match
4441 # exc_value ExcValueNode used internally
4442 # function_name string qualified name of enclosing function
4443 # exc_vars (string * 3) local exception variables
4445 # excinfo_target is never set by the parser, but can be set by a transform
4446 # in order to extract more extensive information about the exception as a
4447 # sys.exc_info()-style tuple into a target variable
4449 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4451 exc_value = None
4452 excinfo_target = None
4454 def analyse_declarations(self, env):
4455 if self.target:
4456 self.target.analyse_target_declaration(env)
4457 if self.excinfo_target is not None:
4458 self.excinfo_target.analyse_target_declaration(env)
4459 self.body.analyse_declarations(env)
4461 def analyse_expressions(self, env):
4462 import ExprNodes
4463 genv = env.global_scope()
4464 self.function_name = env.qualified_name
4465 if self.pattern:
4466 self.pattern.analyse_expressions(env)
4467 self.pattern = self.pattern.coerce_to_pyobject(env)
4469 if self.target:
4470 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4471 self.target.analyse_target_expression(env, self.exc_value)
4472 if self.excinfo_target is not None:
4473 import ExprNodes
4474 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4475 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4476 self.excinfo_tuple.analyse_expressions(env)
4477 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4479 self.body.analyse_expressions(env)
4481 def generate_handling_code(self, code, end_label):
4482 code.mark_pos(self.pos)
4483 if self.pattern:
4484 self.pattern.generate_evaluation_code(code)
4486 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4487 code.putln(
4488 "%s = PyErr_ExceptionMatches(%s);" % (
4489 match_flag,
4490 self.pattern.py_result()))
4491 self.pattern.generate_disposal_code(code)
4492 self.pattern.free_temps(code)
4493 code.putln(
4494 "if (%s) {" %
4495 match_flag)
4496 code.funcstate.release_temp(match_flag)
4497 else:
4498 code.putln("/*except:*/ {")
4500 if not getattr(self.body, 'stats', True):
4501 # most simple case: no exception variable, empty body (pass)
4502 # => reset the exception state, done
4503 code.putln("PyErr_Restore(0,0,0);")
4504 code.put_goto(end_label)
4505 code.putln("}")
4506 return
4508 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4509 manage_ref=True)
4510 for i in xrange(3)]
4511 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4512 # We always have to fetch the exception value even if
4513 # there is no target, because this also normalises the
4514 # exception and stores it in the thread state.
4515 code.globalstate.use_utility_code(get_exception_utility_code)
4516 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4517 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4518 code.error_goto(self.pos)))
4519 for x in exc_vars:
4520 code.put_gotref(x)
4521 if self.target:
4522 self.exc_value.set_var(exc_vars[1])
4523 self.exc_value.generate_evaluation_code(code)
4524 self.target.generate_assignment_code(self.exc_value, code)
4525 if self.excinfo_target is not None:
4526 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4527 node.set_var(tempvar)
4528 self.excinfo_tuple.generate_evaluation_code(code)
4529 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4531 old_break_label, old_continue_label = code.break_label, code.continue_label
4532 code.break_label = code.new_label('except_break')
4533 code.continue_label = code.new_label('except_continue')
4535 old_exc_vars = code.funcstate.exc_vars
4536 code.funcstate.exc_vars = exc_vars
4537 self.body.generate_execution_code(code)
4538 code.funcstate.exc_vars = old_exc_vars
4539 for var in exc_vars:
4540 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4541 code.put_goto(end_label)
4543 if code.label_used(code.break_label):
4544 code.put_label(code.break_label)
4545 for var in exc_vars:
4546 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4547 code.put_goto(old_break_label)
4548 code.break_label = old_break_label
4550 if code.label_used(code.continue_label):
4551 code.put_label(code.continue_label)
4552 for var in exc_vars:
4553 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4554 code.put_goto(old_continue_label)
4555 code.continue_label = old_continue_label
4557 for temp in exc_vars:
4558 code.funcstate.release_temp(temp)
4560 code.putln(
4561 "}")
4563 def annotate(self, code):
4564 if self.pattern:
4565 self.pattern.annotate(code)
4566 if self.target:
4567 self.target.annotate(code)
4568 self.body.annotate(code)
4571 class TryFinallyStatNode(StatNode):
4572 # try ... finally statement
4574 # body StatNode
4575 # finally_clause StatNode
4577 # The plan is that we funnel all continue, break
4578 # return and error gotos into the beginning of the
4579 # finally block, setting a variable to remember which
4580 # one we're doing. At the end of the finally block, we
4581 # switch on the variable to figure out where to go.
4582 # In addition, if we're doing an error, we save the
4583 # exception on entry to the finally block and restore
4584 # it on exit.
4586 child_attrs = ["body", "finally_clause"]
4588 preserve_exception = 1
4590 disallow_continue_in_try_finally = 0
4591 # There doesn't seem to be any point in disallowing
4592 # continue in the try block, since we have no problem
4593 # handling it.
4595 def create_analysed(pos, env, body, finally_clause):
4596 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4597 return node
4598 create_analysed = staticmethod(create_analysed)
4600 def analyse_control_flow(self, env):
4601 env.start_branching(self.pos)
4602 self.body.analyse_control_flow(env)
4603 env.next_branch(self.body.end_pos())
4604 env.finish_branching(self.body.end_pos())
4605 self.finally_clause.analyse_control_flow(env)
4607 def analyse_declarations(self, env):
4608 self.body.analyse_declarations(env)
4609 self.finally_clause.analyse_declarations(env)
4611 def analyse_expressions(self, env):
4612 self.body.analyse_expressions(env)
4613 self.finally_clause.analyse_expressions(env)
4615 nogil_check = Node.gil_error
4616 gil_message = "Try-finally statement"
4618 def generate_execution_code(self, code):
4619 old_error_label = code.error_label
4620 old_labels = code.all_new_labels()
4621 new_labels = code.get_all_labels()
4622 new_error_label = code.error_label
4623 catch_label = code.new_label()
4624 code.putln(
4625 "/*try:*/ {")
4626 if self.disallow_continue_in_try_finally:
4627 was_in_try_finally = code.funcstate.in_try_finally
4628 code.funcstate.in_try_finally = 1
4629 self.body.generate_execution_code(code)
4630 if self.disallow_continue_in_try_finally:
4631 code.funcstate.in_try_finally = was_in_try_finally
4632 code.putln(
4633 "}")
4634 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4635 code.putln(
4636 "/*finally:*/ {")
4637 cases_used = []
4638 error_label_used = 0
4639 for i, new_label in enumerate(new_labels):
4640 if new_label in code.labels_used:
4641 cases_used.append(i)
4642 if new_label == new_error_label:
4643 error_label_used = 1
4644 error_label_case = i
4645 if cases_used:
4646 code.putln(
4647 "int __pyx_why;")
4648 if error_label_used and self.preserve_exception:
4649 code.putln(
4650 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4651 code.putln(
4652 "int %s;" % Naming.exc_lineno_name)
4653 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4654 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4655 code.putln(exc_var_init_zero)
4656 else:
4657 exc_var_init_zero = None
4658 code.use_label(catch_label)
4659 code.putln(
4660 "__pyx_why = 0; goto %s;" % catch_label)
4661 for i in cases_used:
4662 new_label = new_labels[i]
4663 #if new_label and new_label != "<try>":
4664 if new_label == new_error_label and self.preserve_exception:
4665 self.put_error_catcher(code,
4666 new_error_label, i+1, catch_label, temps_to_clean_up)
4667 else:
4668 code.put('%s: ' % new_label)
4669 if exc_var_init_zero:
4670 code.putln(exc_var_init_zero)
4671 code.putln("__pyx_why = %s; goto %s;" % (
4672 i+1,
4673 catch_label))
4674 code.put_label(catch_label)
4675 code.set_all_labels(old_labels)
4676 if error_label_used:
4677 code.new_error_label()
4678 finally_error_label = code.error_label
4679 self.finally_clause.generate_execution_code(code)
4680 if error_label_used:
4681 if finally_error_label in code.labels_used and self.preserve_exception:
4682 over_label = code.new_label()
4683 code.put_goto(over_label);
4684 code.put_label(finally_error_label)
4685 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4686 for var in Naming.exc_vars:
4687 code.putln("Py_XDECREF(%s);" % var)
4688 code.putln("}")
4689 code.put_goto(old_error_label)
4690 code.put_label(over_label)
4691 code.error_label = old_error_label
4692 if cases_used:
4693 code.putln(
4694 "switch (__pyx_why) {")
4695 for i in cases_used:
4696 old_label = old_labels[i]
4697 if old_label == old_error_label and self.preserve_exception:
4698 self.put_error_uncatcher(code, i+1, old_error_label)
4699 else:
4700 code.use_label(old_label)
4701 code.putln(
4702 "case %s: goto %s;" % (
4703 i+1,
4704 old_label))
4705 code.putln(
4706 "}")
4707 code.putln(
4708 "}")
4710 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4711 code.globalstate.use_utility_code(restore_exception_utility_code)
4712 code.putln(
4713 "%s: {" %
4714 error_label)
4715 code.putln(
4716 "__pyx_why = %s;" %
4717 i)
4718 for temp_name, type in temps_to_clean_up:
4719 code.put_xdecref_clear(temp_name, type)
4720 code.putln(
4721 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4722 Naming.exc_vars)
4723 code.putln(
4724 "%s = %s;" % (
4725 Naming.exc_lineno_name, Naming.lineno_cname))
4726 code.put_goto(catch_label)
4727 code.putln("}")
4729 def put_error_uncatcher(self, code, i, error_label):
4730 code.globalstate.use_utility_code(restore_exception_utility_code)
4731 code.putln(
4732 "case %s: {" %
4733 i)
4734 code.putln(
4735 "__Pyx_ErrRestore(%s, %s, %s);" %
4736 Naming.exc_vars)
4737 code.putln(
4738 "%s = %s;" % (
4739 Naming.lineno_cname, Naming.exc_lineno_name))
4740 for var in Naming.exc_vars:
4741 code.putln(
4742 "%s = 0;" %
4743 var)
4744 code.put_goto(error_label)
4745 code.putln(
4746 "}")
4748 def annotate(self, code):
4749 self.body.annotate(code)
4750 self.finally_clause.annotate(code)
4753 class GILStatNode(TryFinallyStatNode):
4754 # 'with gil' or 'with nogil' statement
4756 # state string 'gil' or 'nogil'
4758 # child_attrs = []
4760 preserve_exception = 0
4762 def __init__(self, pos, state, body):
4763 self.state = state
4764 TryFinallyStatNode.__init__(self, pos,
4765 body = body,
4766 finally_clause = GILExitNode(pos, state = state))
4768 def analyse_expressions(self, env):
4769 env.use_utility_code(force_init_threads_utility_code)
4770 was_nogil = env.nogil
4771 env.nogil = 1
4772 TryFinallyStatNode.analyse_expressions(self, env)
4773 env.nogil = was_nogil
4775 nogil_check = None
4777 def generate_execution_code(self, code):
4778 code.mark_pos(self.pos)
4779 if self.state == 'gil':
4780 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4781 else:
4782 code.putln("{ PyThreadState *_save;")
4783 code.putln("Py_UNBLOCK_THREADS")
4784 TryFinallyStatNode.generate_execution_code(self, code)
4785 code.putln("}")
4788 class GILExitNode(StatNode):
4789 # Used as the 'finally' block in a GILStatNode
4791 # state string 'gil' or 'nogil'
4793 child_attrs = []
4795 def analyse_expressions(self, env):
4796 pass
4798 def generate_execution_code(self, code):
4799 if self.state == 'gil':
4800 code.putln("PyGILState_Release();")
4801 else:
4802 code.putln("Py_BLOCK_THREADS")
4805 class CImportStatNode(StatNode):
4806 # cimport statement
4808 # module_name string Qualified name of module being imported
4809 # as_name string or None Name specified in "as" clause, if any
4811 child_attrs = []
4813 def analyse_declarations(self, env):
4814 if not env.is_module_scope:
4815 error(self.pos, "cimport only allowed at module level")
4816 return
4817 module_scope = env.find_module(self.module_name, self.pos)
4818 if "." in self.module_name:
4819 names = [EncodedString(name) for name in self.module_name.split(".")]
4820 top_name = names[0]
4821 top_module_scope = env.context.find_submodule(top_name)
4822 module_scope = top_module_scope
4823 for name in names[1:]:
4824 submodule_scope = module_scope.find_submodule(name)
4825 module_scope.declare_module(name, submodule_scope, self.pos)
4826 module_scope = submodule_scope
4827 if self.as_name:
4828 env.declare_module(self.as_name, module_scope, self.pos)
4829 else:
4830 env.declare_module(top_name, top_module_scope, self.pos)
4831 else:
4832 name = self.as_name or self.module_name
4833 env.declare_module(name, module_scope, self.pos)
4835 def analyse_expressions(self, env):
4836 pass
4838 def generate_execution_code(self, code):
4839 pass
4842 class FromCImportStatNode(StatNode):
4843 # from ... cimport statement
4845 # module_name string Qualified name of module
4846 # imported_names [(pos, name, as_name, kind)] Names to be imported
4848 child_attrs = []
4850 def analyse_declarations(self, env):
4851 if not env.is_module_scope:
4852 error(self.pos, "cimport only allowed at module level")
4853 return
4854 module_scope = env.find_module(self.module_name, self.pos)
4855 env.add_imported_module(module_scope)
4856 for pos, name, as_name, kind in self.imported_names:
4857 if name == "*":
4858 for local_name, entry in module_scope.entries.items():
4859 env.add_imported_entry(local_name, entry, pos)
4860 else:
4861 entry = module_scope.lookup(name)
4862 if entry:
4863 if kind and not self.declaration_matches(entry, kind):
4864 entry.redeclared(pos)
4865 else:
4866 if kind == 'struct' or kind == 'union':
4867 entry = module_scope.declare_struct_or_union(name,
4868 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4869 elif kind == 'class':
4870 entry = module_scope.declare_c_class(name, pos = pos,
4871 module_name = self.module_name)
4872 else:
4873 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4874 if submodule_scope.parent_module is module_scope:
4875 env.declare_module(as_name or name, submodule_scope, self.pos)
4876 else:
4877 error(pos, "Name '%s' not declared in module '%s'"
4878 % (name, self.module_name))
4880 if entry:
4881 local_name = as_name or name
4882 env.add_imported_entry(local_name, entry, pos)
4884 def declaration_matches(self, entry, kind):
4885 if not entry.is_type:
4886 return 0
4887 type = entry.type
4888 if kind == 'class':
4889 if not type.is_extension_type:
4890 return 0
4891 else:
4892 if not type.is_struct_or_union:
4893 return 0
4894 if kind != type.kind:
4895 return 0
4896 return 1
4898 def analyse_expressions(self, env):
4899 pass
4901 def generate_execution_code(self, code):
4902 pass
4905 class FromImportStatNode(StatNode):
4906 # from ... import statement
4908 # module ImportNode
4909 # items [(string, NameNode)]
4910 # interned_items [(string, NameNode, ExprNode)]
4911 # item PyTempNode used internally
4912 # import_star boolean used internally
4914 child_attrs = ["module"]
4915 import_star = 0
4917 def analyse_declarations(self, env):
4918 for name, target in self.items:
4919 if name == "*":
4920 if not env.is_module_scope:
4921 error(self.pos, "import * only allowed at module level")
4922 return
4923 env.has_import_star = 1
4924 self.import_star = 1
4925 else:
4926 target.analyse_target_declaration(env)
4928 def analyse_expressions(self, env):
4929 import ExprNodes
4930 self.module.analyse_expressions(env)
4931 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4932 self.interned_items = []
4933 for name, target in self.items:
4934 if name == '*':
4935 for _, entry in env.entries.items():
4936 if not entry.is_type and entry.type.is_extension_type:
4937 env.use_utility_code(ExprNodes.type_test_utility_code)
4938 break
4939 else:
4940 entry = env.lookup(target.name)
4941 if (entry.is_type and
4942 entry.type.name == name and
4943 entry.type.module_name == self.module.module_name.value):
4944 continue # already cimported
4945 target.analyse_target_expression(env, None)
4946 if target.type is py_object_type:
4947 coerced_item = None
4948 else:
4949 coerced_item = self.item.coerce_to(target.type, env)
4950 self.interned_items.append(
4951 (name, target, coerced_item))
4953 def generate_execution_code(self, code):
4954 self.module.generate_evaluation_code(code)
4955 if self.import_star:
4956 code.putln(
4957 'if (%s(%s) < 0) %s;' % (
4958 Naming.import_star,
4959 self.module.py_result(),
4960 code.error_goto(self.pos)))
4961 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4962 self.item.set_cname(item_temp)
4963 for name, target, coerced_item in self.interned_items:
4964 cname = code.intern_identifier(name)
4965 code.putln(
4966 '%s = PyObject_GetAttr(%s, %s); %s' % (
4967 item_temp,
4968 self.module.py_result(),
4969 cname,
4970 code.error_goto_if_null(item_temp, self.pos)))
4971 code.put_gotref(item_temp)
4972 if coerced_item is None:
4973 target.generate_assignment_code(self.item, code)
4974 else:
4975 coerced_item.allocate_temp_result(code)
4976 coerced_item.generate_result_code(code)
4977 target.generate_assignment_code(coerced_item, code)
4978 code.put_decref_clear(item_temp, py_object_type)
4979 code.funcstate.release_temp(item_temp)
4980 self.module.generate_disposal_code(code)
4981 self.module.free_temps(code)
4985 #------------------------------------------------------------------------------------
4987 # Runtime support code
4989 #------------------------------------------------------------------------------------
4991 utility_function_predeclarations = \
4992 """
4993 #ifndef CYTHON_INLINE
4994 #if defined(__GNUC__)
4995 #define CYTHON_INLINE __inline__
4996 #elif defined(_MSC_VER)
4997 #define CYTHON_INLINE __inline
4998 #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
4999 #define CYTHON_INLINE inline
5000 #else
5001 #define CYTHON_INLINE
5002 #endif
5003 #endif
5005 typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
5007 """
5009 if Options.gcc_branch_hints:
5010 branch_prediction_macros = \
5011 """
5012 #ifdef __GNUC__
5013 /* Test for GCC > 2.95 */
5014 #if __GNUC__ > 2 || \
5015 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
5016 #define likely(x) __builtin_expect(!!(x), 1)
5017 #define unlikely(x) __builtin_expect(!!(x), 0)
5018 #else /* __GNUC__ > 2 ... */
5019 #define likely(x) (x)
5020 #define unlikely(x) (x)
5021 #endif /* __GNUC__ > 2 ... */
5022 #else /* __GNUC__ */
5023 #define likely(x) (x)
5024 #define unlikely(x) (x)
5025 #endif /* __GNUC__ */
5026 """
5027 else:
5028 branch_prediction_macros = \
5029 """
5030 #define likely(x) (x)
5031 #define unlikely(x) (x)
5032 """
5034 #get_name_predeclaration = \
5035 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
5037 #get_name_interned_predeclaration = \
5038 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
5040 #------------------------------------------------------------------------------------
5042 printing_utility_code = UtilityCode(
5043 proto = """
5044 static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/
5045 #if PY_MAJOR_VERSION >= 3
5046 static PyObject* %s = 0;
5047 static PyObject* %s = 0;
5048 #endif
5049 """ % (Naming.print_function, Naming.print_function_kwargs),
5050 cleanup = """
5051 #if PY_MAJOR_VERSION >= 3
5052 Py_CLEAR(%s);
5053 Py_CLEAR(%s);
5054 #endif
5055 """ % (Naming.print_function, Naming.print_function_kwargs),
5056 impl = r"""
5057 #if PY_MAJOR_VERSION < 3
5058 static PyObject *__Pyx_GetStdout(void) {
5059 PyObject *f = PySys_GetObject((char *)"stdout");
5060 if (!f) {
5061 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
5063 return f;
5066 static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
5067 PyObject* v;
5068 int i;
5070 if (!f) {
5071 if (!(f = __Pyx_GetStdout()))
5072 return -1;
5074 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
5075 if (PyFile_SoftSpace(f, 1)) {
5076 if (PyFile_WriteString(" ", f) < 0)
5077 return -1;
5079 v = PyTuple_GET_ITEM(arg_tuple, i);
5080 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
5081 return -1;
5082 if (PyString_Check(v)) {
5083 char *s = PyString_AsString(v);
5084 Py_ssize_t len = PyString_Size(v);
5085 if (len > 0 &&
5086 isspace(Py_CHARMASK(s[len-1])) &&
5087 s[len-1] != ' ')
5088 PyFile_SoftSpace(f, 0);
5091 if (newline) {
5092 if (PyFile_WriteString("\n", f) < 0)
5093 return -1;
5094 PyFile_SoftSpace(f, 0);
5096 return 0;
5099 #else /* Python 3 has a print function */
5101 static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
5102 PyObject* kwargs = 0;
5103 PyObject* result = 0;
5104 PyObject* end_string;
5105 if (unlikely(!%(PRINT_FUNCTION)s)) {
5106 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
5107 if (!%(PRINT_FUNCTION)s)
5108 return -1;
5110 if (stream) {
5111 kwargs = PyDict_New();
5112 if (unlikely(!kwargs))
5113 return -1;
5114 if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0))
5115 goto bad;
5116 if (!newline) {
5117 end_string = PyUnicode_FromStringAndSize(" ", 1);
5118 if (unlikely(!end_string))
5119 goto bad;
5120 if (PyDict_SetItemString(kwargs, "end", end_string) < 0) {
5121 Py_DECREF(end_string);
5122 goto bad;
5124 Py_DECREF(end_string);
5126 } else if (!newline) {
5127 if (unlikely(!%(PRINT_KWARGS)s)) {
5128 %(PRINT_KWARGS)s = PyDict_New();
5129 if (unlikely(!%(PRINT_KWARGS)s))
5130 return -1;
5131 end_string = PyUnicode_FromStringAndSize(" ", 1);
5132 if (unlikely(!end_string))
5133 return -1;
5134 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
5135 Py_DECREF(end_string);
5136 return -1;
5138 Py_DECREF(end_string);
5140 kwargs = %(PRINT_KWARGS)s;
5142 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
5143 if (unlikely(kwargs) && (kwargs != %(PRINT_KWARGS)s))
5144 Py_DECREF(kwargs);
5145 if (!result)
5146 return -1;
5147 Py_DECREF(result);
5148 return 0;
5149 bad:
5150 if (kwargs != %(PRINT_KWARGS)s)
5151 Py_XDECREF(kwargs);
5152 return -1;
5155 #endif
5156 """ % {'BUILTINS' : Naming.builtins_cname,
5157 'PRINT_FUNCTION' : Naming.print_function,
5158 'PRINT_KWARGS' : Naming.print_function_kwargs}
5162 printing_one_utility_code = UtilityCode(
5163 proto = """
5164 static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/
5165 """,
5166 impl = r"""
5167 #if PY_MAJOR_VERSION < 3
5169 static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
5170 if (!f) {
5171 if (!(f = __Pyx_GetStdout()))
5172 return -1;
5174 if (PyFile_SoftSpace(f, 0)) {
5175 if (PyFile_WriteString(" ", f) < 0)
5176 return -1;
5178 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5179 return -1;
5180 if (PyFile_WriteString("\n", f) < 0)
5181 return -1;
5182 return 0;
5183 /* the line below is just to avoid compiler
5184 * compiler warnings about unused functions */
5185 return __Pyx_Print(f, NULL, 0);
5188 #else /* Python 3 has a print function */
5190 static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
5191 int res;
5192 PyObject* arg_tuple = PyTuple_New(1);
5193 if (unlikely(!arg_tuple))
5194 return -1;
5195 Py_INCREF(o);
5196 PyTuple_SET_ITEM(arg_tuple, 0, o);
5197 res = __Pyx_Print(stream, arg_tuple, 1);
5198 Py_DECREF(arg_tuple);
5199 return res;
5202 #endif
5203 """,
5204 requires=[printing_utility_code])
5208 #------------------------------------------------------------------------------------
5210 # Exception raising code
5212 # Exceptions are raised by __Pyx_Raise() and stored as plain
5213 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5214 # 'except' statement, curexc_* is moved over to exc_* by
5215 # __Pyx_GetException()
5217 restore_exception_utility_code = UtilityCode(
5218 proto = """
5219 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5220 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5221 """,
5222 impl = """
5223 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5224 PyObject *tmp_type, *tmp_value, *tmp_tb;
5225 PyThreadState *tstate = PyThreadState_GET();
5227 tmp_type = tstate->curexc_type;
5228 tmp_value = tstate->curexc_value;
5229 tmp_tb = tstate->curexc_traceback;
5230 tstate->curexc_type = type;
5231 tstate->curexc_value = value;
5232 tstate->curexc_traceback = tb;
5233 Py_XDECREF(tmp_type);
5234 Py_XDECREF(tmp_value);
5235 Py_XDECREF(tmp_tb);
5238 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5239 PyThreadState *tstate = PyThreadState_GET();
5240 *type = tstate->curexc_type;
5241 *value = tstate->curexc_value;
5242 *tb = tstate->curexc_traceback;
5244 tstate->curexc_type = 0;
5245 tstate->curexc_value = 0;
5246 tstate->curexc_traceback = 0;
5249 """)
5251 # The following function is based on do_raise() from ceval.c. There
5252 # are separate versions for Python2 and Python3 as exception handling
5253 # has changed quite a lot between the two versions.
5255 raise_utility_code = UtilityCode(
5256 proto = """
5257 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5258 """,
5259 impl = """
5260 #if PY_MAJOR_VERSION < 3
5261 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5262 Py_XINCREF(type);
5263 Py_XINCREF(value);
5264 Py_XINCREF(tb);
5265 /* First, check the traceback argument, replacing None with NULL. */
5266 if (tb == Py_None) {
5267 Py_DECREF(tb);
5268 tb = 0;
5270 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5271 PyErr_SetString(PyExc_TypeError,
5272 "raise: arg 3 must be a traceback or None");
5273 goto raise_error;
5275 /* Next, replace a missing value with None */
5276 if (value == NULL) {
5277 value = Py_None;
5278 Py_INCREF(value);
5280 #if PY_VERSION_HEX < 0x02050000
5281 if (!PyClass_Check(type))
5282 #else
5283 if (!PyType_Check(type))
5284 #endif
5286 /* Raising an instance. The value should be a dummy. */
5287 if (value != Py_None) {
5288 PyErr_SetString(PyExc_TypeError,
5289 "instance exception may not have a separate value");
5290 goto raise_error;
5292 /* Normalize to raise <class>, <instance> */
5293 Py_DECREF(value);
5294 value = type;
5295 #if PY_VERSION_HEX < 0x02050000
5296 if (PyInstance_Check(type)) {
5297 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5298 Py_INCREF(type);
5300 else {
5301 type = 0;
5302 PyErr_SetString(PyExc_TypeError,
5303 "raise: exception must be an old-style class or instance");
5304 goto raise_error;
5306 #else
5307 type = (PyObject*) Py_TYPE(type);
5308 Py_INCREF(type);
5309 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5310 PyErr_SetString(PyExc_TypeError,
5311 "raise: exception class must be a subclass of BaseException");
5312 goto raise_error;
5314 #endif
5317 __Pyx_ErrRestore(type, value, tb);
5318 return;
5319 raise_error:
5320 Py_XDECREF(value);
5321 Py_XDECREF(type);
5322 Py_XDECREF(tb);
5323 return;
5326 #else /* Python 3+ */
5328 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5329 if (tb == Py_None) {
5330 tb = 0;
5331 } else if (tb && !PyTraceBack_Check(tb)) {
5332 PyErr_SetString(PyExc_TypeError,
5333 "raise: arg 3 must be a traceback or None");
5334 goto bad;
5336 if (value == Py_None)
5337 value = 0;
5339 if (PyExceptionInstance_Check(type)) {
5340 if (value) {
5341 PyErr_SetString(PyExc_TypeError,
5342 "instance exception may not have a separate value");
5343 goto bad;
5345 value = type;
5346 type = (PyObject*) Py_TYPE(value);
5347 } else if (!PyExceptionClass_Check(type)) {
5348 PyErr_SetString(PyExc_TypeError,
5349 "raise: exception class must be a subclass of BaseException");
5350 goto bad;
5353 PyErr_SetObject(type, value);
5355 if (tb) {
5356 PyThreadState *tstate = PyThreadState_GET();
5357 PyObject* tmp_tb = tstate->curexc_traceback;
5358 if (tb != tmp_tb) {
5359 Py_INCREF(tb);
5360 tstate->curexc_traceback = tb;
5361 Py_XDECREF(tmp_tb);
5365 bad:
5366 return;
5368 #endif
5369 """,
5370 requires=[restore_exception_utility_code])
5372 #------------------------------------------------------------------------------------
5374 get_exception_utility_code = UtilityCode(
5375 proto = """
5376 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5377 """,
5378 impl = """
5379 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5380 PyObject *local_type, *local_value, *local_tb;
5381 PyObject *tmp_type, *tmp_value, *tmp_tb;
5382 PyThreadState *tstate = PyThreadState_GET();
5383 local_type = tstate->curexc_type;
5384 local_value = tstate->curexc_value;
5385 local_tb = tstate->curexc_traceback;
5386 tstate->curexc_type = 0;
5387 tstate->curexc_value = 0;
5388 tstate->curexc_traceback = 0;
5389 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5390 if (unlikely(tstate->curexc_type))
5391 goto bad;
5392 #if PY_MAJOR_VERSION >= 3
5393 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5394 goto bad;
5395 #endif
5396 *type = local_type;
5397 *value = local_value;
5398 *tb = local_tb;
5399 Py_INCREF(local_type);
5400 Py_INCREF(local_value);
5401 Py_INCREF(local_tb);
5402 tmp_type = tstate->exc_type;
5403 tmp_value = tstate->exc_value;
5404 tmp_tb = tstate->exc_traceback;
5405 tstate->exc_type = local_type;
5406 tstate->exc_value = local_value;
5407 tstate->exc_traceback = local_tb;
5408 /* Make sure tstate is in a consistent state when we XDECREF
5409 these objects (XDECREF may run arbitrary code). */
5410 Py_XDECREF(tmp_type);
5411 Py_XDECREF(tmp_value);
5412 Py_XDECREF(tmp_tb);
5413 return 0;
5414 bad:
5415 *type = 0;
5416 *value = 0;
5417 *tb = 0;
5418 Py_XDECREF(local_type);
5419 Py_XDECREF(local_value);
5420 Py_XDECREF(local_tb);
5421 return -1;
5424 """)
5426 #------------------------------------------------------------------------------------
5428 get_exception_tuple_utility_code = UtilityCode(proto="""
5429 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5430 """,
5431 # I doubt that calling __Pyx_GetException() here is correct as it moves
5432 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5433 # exception handlers later on from receiving it.
5434 impl = """
5435 static PyObject *__Pyx_GetExceptionTuple(void) {
5436 PyObject *type = NULL, *value = NULL, *tb = NULL;
5437 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5438 PyObject* exc_info = PyTuple_New(3);
5439 if (exc_info) {
5440 Py_INCREF(type);
5441 Py_INCREF(value);
5442 Py_INCREF(tb);
5443 PyTuple_SET_ITEM(exc_info, 0, type);
5444 PyTuple_SET_ITEM(exc_info, 1, value);
5445 PyTuple_SET_ITEM(exc_info, 2, tb);
5446 return exc_info;
5449 return NULL;
5451 """,
5452 requires=[get_exception_utility_code])
5454 #------------------------------------------------------------------------------------
5456 reset_exception_utility_code = UtilityCode(
5457 proto = """
5458 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5459 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5460 """,
5461 impl = """
5462 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5463 PyThreadState *tstate = PyThreadState_GET();
5464 *type = tstate->exc_type;
5465 *value = tstate->exc_value;
5466 *tb = tstate->exc_traceback;
5467 Py_XINCREF(*type);
5468 Py_XINCREF(*value);
5469 Py_XINCREF(*tb);
5472 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5473 PyObject *tmp_type, *tmp_value, *tmp_tb;
5474 PyThreadState *tstate = PyThreadState_GET();
5475 tmp_type = tstate->exc_type;
5476 tmp_value = tstate->exc_value;
5477 tmp_tb = tstate->exc_traceback;
5478 tstate->exc_type = type;
5479 tstate->exc_value = value;
5480 tstate->exc_traceback = tb;
5481 Py_XDECREF(tmp_type);
5482 Py_XDECREF(tmp_value);
5483 Py_XDECREF(tmp_tb);
5485 """)
5487 #------------------------------------------------------------------------------------
5489 arg_type_test_utility_code = UtilityCode(
5490 proto = """
5491 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5492 const char *name, int exact); /*proto*/
5493 """,
5494 impl = """
5495 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5496 const char *name, int exact)
5498 if (!type) {
5499 PyErr_Format(PyExc_SystemError, "Missing type object");
5500 return 0;
5502 if (none_allowed && obj == Py_None) return 1;
5503 else if (exact) {
5504 if (Py_TYPE(obj) == type) return 1;
5506 else {
5507 if (PyObject_TypeCheck(obj, type)) return 1;
5509 PyErr_Format(PyExc_TypeError,
5510 "Argument '%s' has incorrect type (expected %s, got %s)",
5511 name, type->tp_name, Py_TYPE(obj)->tp_name);
5512 return 0;
5514 """)
5516 #------------------------------------------------------------------------------------
5518 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5519 # many or too few positional arguments were found. This handles
5520 # Py_ssize_t formatting correctly.
5522 raise_argtuple_invalid_utility_code = UtilityCode(
5523 proto = """
5524 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5525 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5526 """,
5527 impl = """
5528 static void __Pyx_RaiseArgtupleInvalid(
5529 const char* func_name,
5530 int exact,
5531 Py_ssize_t num_min,
5532 Py_ssize_t num_max,
5533 Py_ssize_t num_found)
5535 Py_ssize_t num_expected;
5536 const char *number, *more_or_less;
5538 if (num_found < num_min) {
5539 num_expected = num_min;
5540 more_or_less = "at least";
5541 } else {
5542 num_expected = num_max;
5543 more_or_less = "at most";
5545 if (exact) {
5546 more_or_less = "exactly";
5548 number = (num_expected == 1) ? "" : "s";
5549 PyErr_Format(PyExc_TypeError,
5550 #if PY_VERSION_HEX < 0x02050000
5551 "%s() takes %s %d positional argument%s (%d given)",
5552 #else
5553 "%s() takes %s %zd positional argument%s (%zd given)",
5554 #endif
5555 func_name, more_or_less, num_expected, number, num_found);
5557 """)
5559 raise_keyword_required_utility_code = UtilityCode(
5560 proto = """
5561 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5562 """,
5563 impl = """
5564 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(
5565 const char* func_name,
5566 PyObject* kw_name)
5568 PyErr_Format(PyExc_TypeError,
5569 #if PY_MAJOR_VERSION >= 3
5570 "%s() needs keyword-only argument %U", func_name, kw_name);
5571 #else
5572 "%s() needs keyword-only argument %s", func_name,
5573 PyString_AS_STRING(kw_name));
5574 #endif
5576 """)
5578 raise_double_keywords_utility_code = UtilityCode(
5579 proto = """
5580 static void __Pyx_RaiseDoubleKeywordsError(
5581 const char* func_name, PyObject* kw_name); /*proto*/
5582 """,
5583 impl = """
5584 static void __Pyx_RaiseDoubleKeywordsError(
5585 const char* func_name,
5586 PyObject* kw_name)
5588 PyErr_Format(PyExc_TypeError,
5589 #if PY_MAJOR_VERSION >= 3
5590 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5591 #else
5592 "%s() got multiple values for keyword argument '%s'", func_name,
5593 PyString_AS_STRING(kw_name));
5594 #endif
5596 """)
5598 #------------------------------------------------------------------------------------
5600 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5601 # were passed to a function, or if any keywords were passed to a
5602 # function that does not accept them.
5604 keyword_string_check_utility_code = UtilityCode(
5605 proto = """
5606 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5607 const char* function_name, int kw_allowed); /*proto*/
5608 """,
5609 impl = """
5610 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
5611 PyObject *kwdict,
5612 const char* function_name,
5613 int kw_allowed)
5615 PyObject* key = 0;
5616 Py_ssize_t pos = 0;
5617 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5618 #if PY_MAJOR_VERSION < 3
5619 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5620 #else
5621 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5622 #endif
5623 goto invalid_keyword_type;
5625 if ((!kw_allowed) && unlikely(key))
5626 goto invalid_keyword;
5627 return 1;
5628 invalid_keyword_type:
5629 PyErr_Format(PyExc_TypeError,
5630 "%s() keywords must be strings", function_name);
5631 return 0;
5632 invalid_keyword:
5633 PyErr_Format(PyExc_TypeError,
5634 #if PY_MAJOR_VERSION < 3
5635 "%s() got an unexpected keyword argument '%s'",
5636 function_name, PyString_AsString(key));
5637 #else
5638 "%s() got an unexpected keyword argument '%U'",
5639 function_name, key);
5640 #endif
5641 return 0;
5643 """)
5645 #------------------------------------------------------------------------------------
5647 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5648 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5649 # keywords will raise an invalid keyword error.
5651 # Three kinds of errors are checked: 1) non-string keywords, 2)
5652 # unexpected keywords and 3) overlap with positional arguments.
5654 # If num_posargs is greater 0, it denotes the number of positional
5655 # arguments that were passed and that must therefore not appear
5656 # amongst the keywords as well.
5658 # This method does not check for required keyword arguments.
5661 parse_keywords_utility_code = UtilityCode(
5662 proto = """
5663 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5664 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5665 const char* function_name); /*proto*/
5666 """,
5667 impl = """
5668 static int __Pyx_ParseOptionalKeywords(
5669 PyObject *kwds,
5670 PyObject **argnames[],
5671 PyObject *kwds2,
5672 PyObject *values[],
5673 Py_ssize_t num_pos_args,
5674 const char* function_name)
5676 PyObject *key = 0, *value = 0;
5677 Py_ssize_t pos = 0;
5678 PyObject*** name;
5679 PyObject*** first_kw_arg = argnames + num_pos_args;
5681 while (PyDict_Next(kwds, &pos, &key, &value)) {
5682 name = first_kw_arg;
5683 while (*name && (**name != key)) name++;
5684 if (*name) {
5685 values[name-argnames] = value;
5686 } else {
5687 #if PY_MAJOR_VERSION < 3
5688 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5689 #else
5690 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5691 #endif
5692 goto invalid_keyword_type;
5693 } else {
5694 for (name = first_kw_arg; *name; name++) {
5695 #if PY_MAJOR_VERSION >= 3
5696 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5697 PyUnicode_Compare(**name, key) == 0) break;
5698 #else
5699 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5700 _PyString_Eq(**name, key)) break;
5701 #endif
5703 if (*name) {
5704 values[name-argnames] = value;
5705 } else {
5706 /* unexpected keyword found */
5707 for (name=argnames; name != first_kw_arg; name++) {
5708 if (**name == key) goto arg_passed_twice;
5709 #if PY_MAJOR_VERSION >= 3
5710 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5711 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5712 #else
5713 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5714 _PyString_Eq(**name, key)) goto arg_passed_twice;
5715 #endif
5717 if (kwds2) {
5718 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5719 } else {
5720 goto invalid_keyword;
5726 return 0;
5727 arg_passed_twice:
5728 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5729 goto bad;
5730 invalid_keyword_type:
5731 PyErr_Format(PyExc_TypeError,
5732 "%s() keywords must be strings", function_name);
5733 goto bad;
5734 invalid_keyword:
5735 PyErr_Format(PyExc_TypeError,
5736 #if PY_MAJOR_VERSION < 3
5737 "%s() got an unexpected keyword argument '%s'",
5738 function_name, PyString_AsString(key));
5739 #else
5740 "%s() got an unexpected keyword argument '%U'",
5741 function_name, key);
5742 #endif
5743 bad:
5744 return -1;
5746 """)
5748 #------------------------------------------------------------------------------------
5750 traceback_utility_code = UtilityCode(
5751 proto = """
5752 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5753 """,
5754 impl = """
5755 #include "compile.h"
5756 #include "frameobject.h"
5757 #include "traceback.h"
5759 static void __Pyx_AddTraceback(const char *funcname) {
5760 PyObject *py_srcfile = 0;
5761 PyObject *py_funcname = 0;
5762 PyObject *py_globals = 0;
5763 PyCodeObject *py_code = 0;
5764 PyFrameObject *py_frame = 0;
5766 #if PY_MAJOR_VERSION < 3
5767 py_srcfile = PyString_FromString(%(FILENAME)s);
5768 #else
5769 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5770 #endif
5771 if (!py_srcfile) goto bad;
5772 if (%(CLINENO)s) {
5773 #if PY_MAJOR_VERSION < 3
5774 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5775 #else
5776 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5777 #endif
5779 else {
5780 #if PY_MAJOR_VERSION < 3
5781 py_funcname = PyString_FromString(funcname);
5782 #else
5783 py_funcname = PyUnicode_FromString(funcname);
5784 #endif
5786 if (!py_funcname) goto bad;
5787 py_globals = PyModule_GetDict(%(GLOBALS)s);
5788 if (!py_globals) goto bad;
5789 py_code = PyCode_New(
5790 0, /*int argcount,*/
5791 #if PY_MAJOR_VERSION >= 3
5792 0, /*int kwonlyargcount,*/
5793 #endif
5794 0, /*int nlocals,*/
5795 0, /*int stacksize,*/
5796 0, /*int flags,*/
5797 %(EMPTY_BYTES)s, /*PyObject *code,*/
5798 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5799 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5800 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5801 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5802 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5803 py_srcfile, /*PyObject *filename,*/
5804 py_funcname, /*PyObject *name,*/
5805 %(LINENO)s, /*int firstlineno,*/
5806 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5807 );
5808 if (!py_code) goto bad;
5809 py_frame = PyFrame_New(
5810 PyThreadState_GET(), /*PyThreadState *tstate,*/
5811 py_code, /*PyCodeObject *code,*/
5812 py_globals, /*PyObject *globals,*/
5813 0 /*PyObject *locals*/
5814 );
5815 if (!py_frame) goto bad;
5816 py_frame->f_lineno = %(LINENO)s;
5817 PyTraceBack_Here(py_frame);
5818 bad:
5819 Py_XDECREF(py_srcfile);
5820 Py_XDECREF(py_funcname);
5821 Py_XDECREF(py_code);
5822 Py_XDECREF(py_frame);
5824 """ % {
5825 'FILENAME': Naming.filename_cname,
5826 'LINENO': Naming.lineno_cname,
5827 'CFILENAME': Naming.cfilenm_cname,
5828 'CLINENO': Naming.clineno_cname,
5829 'GLOBALS': Naming.module_cname,
5830 'EMPTY_TUPLE' : Naming.empty_tuple,
5831 'EMPTY_BYTES' : Naming.empty_bytes,
5832 })
5834 #------------------------------------------------------------------------------------
5836 unraisable_exception_utility_code = UtilityCode(
5837 proto = """
5838 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5839 """,
5840 impl = """
5841 static void __Pyx_WriteUnraisable(const char *name) {
5842 PyObject *old_exc, *old_val, *old_tb;
5843 PyObject *ctx;
5844 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5845 #if PY_MAJOR_VERSION < 3
5846 ctx = PyString_FromString(name);
5847 #else
5848 ctx = PyUnicode_FromString(name);
5849 #endif
5850 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5851 if (!ctx) {
5852 PyErr_WriteUnraisable(Py_None);
5853 } else {
5854 PyErr_WriteUnraisable(ctx);
5855 Py_DECREF(ctx);
5858 """,
5859 requires=[restore_exception_utility_code])
5861 #------------------------------------------------------------------------------------
5863 set_vtable_utility_code = UtilityCode(
5864 proto = """
5865 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5866 """,
5867 impl = """
5868 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5869 #if PY_VERSION_HEX < 0x03010000
5870 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5871 #else
5872 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5873 #endif
5874 if (!ob)
5875 goto bad;
5876 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5877 goto bad;
5878 Py_DECREF(ob);
5879 return 0;
5880 bad:
5881 Py_XDECREF(ob);
5882 return -1;
5884 """)
5886 #------------------------------------------------------------------------------------
5888 get_vtable_utility_code = UtilityCode(
5889 proto = """
5890 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5891 """,
5892 impl = r"""
5893 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5894 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5895 if (!ob)
5896 goto bad;
5897 #if PY_VERSION_HEX < 0x03010000
5898 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5899 #else
5900 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5901 #endif
5902 if (!*(void **)vtabptr)
5903 goto bad;
5904 Py_DECREF(ob);
5905 return 0;
5906 bad:
5907 Py_XDECREF(ob);
5908 return -1;
5910 """)
5912 #------------------------------------------------------------------------------------
5914 init_string_tab_utility_code = UtilityCode(
5915 proto = """
5916 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5917 """,
5918 impl = """
5919 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5920 while (t->p) {
5921 #if PY_MAJOR_VERSION < 3
5922 if (t->is_unicode) {
5923 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5924 } else if (t->intern) {
5925 *t->p = PyString_InternFromString(t->s);
5926 } else {
5927 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5929 #else /* Python 3+ has unicode identifiers */
5930 if (t->is_unicode | t->is_str) {
5931 if (t->intern) {
5932 *t->p = PyUnicode_InternFromString(t->s);
5933 } else if (t->encoding) {
5934 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5935 } else {
5936 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5938 } else {
5939 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5941 #endif
5942 if (!*t->p)
5943 return -1;
5944 ++t;
5946 return 0;
5948 """)
5950 #------------------------------------------------------------------------------------
5952 force_init_threads_utility_code = UtilityCode(
5953 proto="""
5954 #ifndef __PYX_FORCE_INIT_THREADS
5955 #if PY_VERSION_HEX < 0x02040200
5956 #define __PYX_FORCE_INIT_THREADS 1
5957 #else
5958 #define __PYX_FORCE_INIT_THREADS 0
5959 #endif
5960 #endif
5961 """)
5963 #------------------------------------------------------------------------------------
5965 # Note that cPython ignores PyTrace_EXCEPTION,
5966 # but maybe some other profilers don't.
5968 profile_utility_code = UtilityCode(proto="""
5969 #ifndef CYTHON_PROFILE
5970 #define CYTHON_PROFILE 1
5971 #endif
5973 #ifndef CYTHON_PROFILE_REUSE_FRAME
5974 #define CYTHON_PROFILE_REUSE_FRAME 0
5975 #endif
5977 #if CYTHON_PROFILE
5979 #include "compile.h"
5980 #include "frameobject.h"
5981 #include "traceback.h"
5983 #if CYTHON_PROFILE_REUSE_FRAME
5984 #define CYTHON_FRAME_MODIFIER static
5985 #define CYTHON_FRAME_DEL
5986 #else
5987 #define CYTHON_FRAME_MODIFIER
5988 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5989 #endif
5991 #define __Pyx_TraceDeclarations \\
5992 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5993 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5994 int __Pyx_use_tracing = 0;
5996 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5997 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5998 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
6001 #define __Pyx_TraceException() \\
6002 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6003 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
6004 if (exc_info) { \\
6005 PyThreadState_GET()->c_profilefunc( \\
6006 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
6007 Py_DECREF(exc_info); \\
6008 } \\
6011 #define __Pyx_TraceReturn(result) \\
6012 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6013 PyThreadState_GET()->c_profilefunc( \\
6014 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
6015 CYTHON_FRAME_DEL; \\
6018 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6019 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6021 #else
6023 #define __Pyx_TraceDeclarations
6024 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
6025 #define __Pyx_TraceException()
6026 #define __Pyx_TraceReturn(result)
6028 #endif /* CYTHON_PROFILE */
6029 """
6030 % {
6031 "FRAME": Naming.frame_cname,
6032 "FRAME_CODE": Naming.frame_code_cname,
6033 },
6034 impl = """
6036 #if CYTHON_PROFILE
6038 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
6039 PyFrameObject** frame,
6040 const char *funcname,
6041 const char *srcfile,
6042 int firstlineno) {
6043 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
6044 if (*code == NULL) {
6045 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
6046 if (*code == NULL) return 0;
6048 *frame = PyFrame_New(
6049 PyThreadState_GET(), /*PyThreadState *tstate*/
6050 *code, /*PyCodeObject *code*/
6051 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
6052 0 /*PyObject *locals*/
6053 );
6054 if (*frame == NULL) return 0;
6056 else {
6057 (*frame)->f_tstate = PyThreadState_GET();
6059 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
6062 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
6063 PyObject *py_srcfile = 0;
6064 PyObject *py_funcname = 0;
6065 PyCodeObject *py_code = 0;
6067 #if PY_MAJOR_VERSION < 3
6068 py_funcname = PyString_FromString(funcname);
6069 py_srcfile = PyString_FromString(srcfile);
6070 #else
6071 py_funcname = PyUnicode_FromString(funcname);
6072 py_srcfile = PyUnicode_FromString(srcfile);
6073 #endif
6074 if (!py_funcname | !py_srcfile) goto bad;
6076 py_code = PyCode_New(
6077 0, /*int argcount,*/
6078 #if PY_MAJOR_VERSION >= 3
6079 0, /*int kwonlyargcount,*/
6080 #endif
6081 0, /*int nlocals,*/
6082 0, /*int stacksize,*/
6083 0, /*int flags,*/
6084 %(EMPTY_BYTES)s, /*PyObject *code,*/
6085 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6086 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6087 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6088 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6089 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6090 py_srcfile, /*PyObject *filename,*/
6091 py_funcname, /*PyObject *name,*/
6092 firstlineno, /*int firstlineno,*/
6093 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6094 );
6096 bad:
6097 Py_XDECREF(py_srcfile);
6098 Py_XDECREF(py_funcname);
6100 return py_code;
6103 #endif /* CYTHON_PROFILE */
6104 """ % {
6105 'EMPTY_TUPLE' : Naming.empty_tuple,
6106 'EMPTY_BYTES' : Naming.empty_bytes,
6107 "MODULE": Naming.module_cname,
6108 })