Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 3049:6c0c2ae56034
implemented 'print >> stream'
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Tue Mar 09 09:29:47 2010 +0100 (2 years ago) |
| parents | 058a70c40bf0 |
| children | 1ff8b3b0eda2 4d45490f6611 |
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 # need_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 need_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 == 'public'
916 and base_type.is_pyobject
917 and (base_type.is_builtin_type or base_type.is_extension_type)):
918 self.need_properties = []
919 need_property = True
920 visibility = 'private'
921 else:
922 need_property = False
923 visibility = self.visibility
925 for declarator in self.declarators:
926 name_declarator, type = declarator.analyse(base_type, env)
927 if not type.is_complete():
928 if not (self.visibility == 'extern' and type.is_array):
929 error(declarator.pos,
930 "Variable type '%s' is incomplete" % type)
931 if self.visibility == 'extern' and type.is_pyobject:
932 error(declarator.pos,
933 "Python object cannot be declared extern")
934 name = name_declarator.name
935 cname = name_declarator.cname
936 if name == '':
937 error(declarator.pos, "Missing name in declaration.")
938 return
939 if type.is_cfunction:
940 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
941 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
942 api = self.api)
943 if entry is not None:
944 entry.directive_locals = self.directive_locals
945 else:
946 if self.directive_locals:
947 s.error("Decorators can only be followed by functions")
948 if self.in_pxd and self.visibility != 'extern':
949 error(self.pos,
950 "Only 'extern' C variable declaration allowed in .pxd file")
951 entry = dest_scope.declare_var(name, type, declarator.pos,
952 cname = cname, visibility = visibility, is_cdef = 1)
953 if need_property:
954 self.need_properties.append(entry)
955 entry.needs_property = 1
958 class CStructOrUnionDefNode(StatNode):
959 # name string
960 # cname string or None
961 # kind "struct" or "union"
962 # typedef_flag boolean
963 # visibility "public" or "private"
964 # in_pxd boolean
965 # attributes [CVarDefNode] or None
966 # entry Entry
967 # packed boolean
969 child_attrs = ["attributes"]
971 def analyse_declarations(self, env):
972 scope = None
973 if self.visibility == 'extern' and self.packed:
974 error(self.pos, "Cannot declare extern struct as 'packed'")
975 if self.attributes is not None:
976 scope = StructOrUnionScope(self.name)
977 self.entry = env.declare_struct_or_union(
978 self.name, self.kind, scope, self.typedef_flag, self.pos,
979 self.cname, visibility = self.visibility, packed = self.packed)
980 if self.attributes is not None:
981 if self.in_pxd and not env.in_cinclude:
982 self.entry.defined_in_pxd = 1
983 for attr in self.attributes:
984 attr.analyse_declarations(env, scope)
985 if self.visibility != 'extern':
986 need_typedef_indirection = False
987 for attr in scope.var_entries:
988 type = attr.type
989 while type.is_array:
990 type = type.base_type
991 if type == self.entry.type:
992 error(attr.pos, "Struct cannot contain itself as a member.")
993 if self.typedef_flag:
994 while type.is_ptr:
995 type = type.base_type
996 if type == self.entry.type:
997 need_typedef_indirection = True
998 if need_typedef_indirection:
999 # C can't handle typedef structs that refer to themselves.
1000 struct_entry = self.entry
1001 self.entry = env.declare_typedef(
1002 self.name, struct_entry.type, self.pos,
1003 cname = self.cname, visibility='ignore')
1004 struct_entry.type.typedef_flag = False
1005 # FIXME: this might be considered a hack ;-)
1006 struct_entry.cname = struct_entry.type.cname = \
1007 '_' + self.entry.type.typedef_cname
1009 def analyse_expressions(self, env):
1010 pass
1012 def generate_execution_code(self, code):
1013 pass
1016 class CppClassNode(CStructOrUnionDefNode):
1018 # name string
1019 # cname string or None
1020 # visibility "extern"
1021 # in_pxd boolean
1022 # attributes [CVarDefNode] or None
1023 # entry Entry
1024 # base_classes [string]
1025 # templates [string] or None
1027 def analyse_declarations(self, env):
1028 scope = None
1029 if len(self.attributes) != 0:
1030 scope = CppClassScope(self.name, env)
1031 else:
1032 self.attributes = None
1033 base_class_types = []
1034 for base_class_name in self.base_classes:
1035 base_class_entry = env.lookup(base_class_name)
1036 if base_class_entry is None:
1037 error(self.pos, "'%s' not found" % base_class_name)
1038 elif not base_class_entry.is_type or not base_class_entry.type.is_cpp_class:
1039 error(self.pos, "'%s' is not a cpp class type" % base_class_name)
1040 else:
1041 base_class_types.append(base_class_entry.type)
1042 if self.templates is None:
1043 template_types = None
1044 else:
1045 template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1046 self.entry = env.declare_cpp_class(
1047 self.name, scope, self.pos,
1048 self.cname, base_class_types, visibility = self.visibility, templates = template_types)
1049 self.entry.is_cpp_class = 1
1050 if self.attributes is not None:
1051 if self.in_pxd and not env.in_cinclude:
1052 self.entry.defined_in_pxd = 1
1053 for attr in self.attributes:
1054 attr.analyse_declarations(scope)
1056 class CEnumDefNode(StatNode):
1057 # name string or None
1058 # cname string or None
1059 # items [CEnumDefItemNode]
1060 # typedef_flag boolean
1061 # visibility "public" or "private"
1062 # in_pxd boolean
1063 # entry Entry
1065 child_attrs = ["items"]
1067 def analyse_declarations(self, env):
1068 self.entry = env.declare_enum(self.name, self.pos,
1069 cname = self.cname, typedef_flag = self.typedef_flag,
1070 visibility = self.visibility)
1071 if self.items is not None:
1072 if self.in_pxd and not env.in_cinclude:
1073 self.entry.defined_in_pxd = 1
1074 for item in self.items:
1075 item.analyse_declarations(env, self.entry)
1077 def analyse_expressions(self, env):
1078 pass
1080 def generate_execution_code(self, code):
1081 if self.visibility == 'public':
1082 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
1083 for item in self.entry.enum_values:
1084 code.putln("%s = PyInt_FromLong(%s); %s" % (
1085 temp,
1086 item.cname,
1087 code.error_goto_if_null(temp, item.pos)))
1088 code.put_gotref(temp)
1089 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
1090 Naming.module_cname,
1091 item.name,
1092 temp,
1093 code.error_goto(item.pos)))
1094 code.put_decref_clear(temp, PyrexTypes.py_object_type)
1095 code.funcstate.release_temp(temp)
1098 class CEnumDefItemNode(StatNode):
1099 # name string
1100 # cname string or None
1101 # value ExprNode or None
1103 child_attrs = ["value"]
1105 def analyse_declarations(self, env, enum_entry):
1106 if self.value:
1107 self.value.analyse_const_expression(env)
1108 if not self.value.type.is_int:
1109 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
1110 self.value.analyse_const_expression(env)
1111 entry = env.declare_const(self.name, enum_entry.type,
1112 self.value, self.pos, cname = self.cname,
1113 visibility = enum_entry.visibility)
1114 enum_entry.enum_values.append(entry)
1117 class CTypeDefNode(StatNode):
1118 # base_type CBaseTypeNode
1119 # declarator CDeclaratorNode
1120 # visibility "public" or "private"
1121 # in_pxd boolean
1123 child_attrs = ["base_type", "declarator"]
1125 def analyse_declarations(self, env):
1126 base = self.base_type.analyse(env)
1127 name_declarator, type = self.declarator.analyse(base, env)
1128 name = name_declarator.name
1129 cname = name_declarator.cname
1130 entry = env.declare_typedef(name, type, self.pos,
1131 cname = cname, visibility = self.visibility)
1132 if self.in_pxd and not env.in_cinclude:
1133 entry.defined_in_pxd = 1
1135 def analyse_expressions(self, env):
1136 pass
1137 def generate_execution_code(self, code):
1138 pass
1141 class FuncDefNode(StatNode, BlockNode):
1142 # Base class for function definition nodes.
1143 #
1144 # return_type PyrexType
1145 # #filename string C name of filename string const
1146 # entry Symtab.Entry
1147 # needs_closure boolean Whether or not this function has inner functions/classes/yield
1148 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1150 py_func = None
1151 assmt = None
1152 needs_closure = False
1153 modifiers = []
1155 def analyse_default_values(self, env):
1156 genv = env.global_scope()
1157 default_seen = 0
1158 for arg in self.args:
1159 if arg.default:
1160 default_seen = 1
1161 if arg.is_generic:
1162 arg.default.analyse_types(env)
1163 arg.default = arg.default.coerce_to(arg.type, genv)
1164 else:
1165 error(arg.pos,
1166 "This argument cannot have a default value")
1167 arg.default = None
1168 elif arg.kw_only:
1169 default_seen = 1
1170 elif default_seen:
1171 error(arg.pos, "Non-default argument following default argument")
1173 def need_gil_acquisition(self, lenv):
1174 return 0
1176 def create_local_scope(self, env):
1177 genv = env
1178 while genv.is_py_class_scope or genv.is_c_class_scope:
1179 genv = env.outer_scope
1180 if self.needs_closure:
1181 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1182 else:
1183 lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
1184 lenv.return_type = self.return_type
1185 type = self.entry.type
1186 if type.is_cfunction:
1187 lenv.nogil = type.nogil and not type.with_gil
1188 self.local_scope = lenv
1189 lenv.directives = env.directives
1190 return lenv
1192 def generate_function_definitions(self, env, code):
1193 import Buffer
1195 lenv = self.local_scope
1197 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1198 self.entry.scope.is_c_class_scope)
1200 profile = code.globalstate.directives['profile']
1201 if profile:
1202 if lenv.nogil:
1203 error(self.pos, "Cannot profile nogil function.")
1204 code.globalstate.use_utility_code(profile_utility_code)
1206 # Generate C code for header and body of function
1207 code.enter_cfunc_scope()
1208 code.return_from_error_cleanup_label = code.new_label()
1210 # ----- Top-level constants used by this function
1211 code.mark_pos(self.pos)
1212 self.generate_cached_builtins_decls(lenv, code)
1213 # ----- Function header
1214 code.putln("")
1215 if self.py_func:
1216 self.py_func.generate_function_header(code,
1217 with_pymethdef = env.is_py_class_scope,
1218 proto_only=True)
1219 self.generate_function_header(code,
1220 with_pymethdef = env.is_py_class_scope)
1221 # ----- Local variable declarations
1222 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1223 self.generate_argument_declarations(lenv, code)
1224 if self.needs_closure:
1225 code.putln("/* TODO: declare and create scope object */")
1226 code.put_var_declarations(lenv.var_entries)
1227 init = ""
1228 if not self.return_type.is_void:
1229 if self.return_type.is_pyobject:
1230 init = " = NULL"
1231 code.putln(
1232 "%s%s;" %
1233 (self.return_type.declaration_code(
1234 Naming.retval_cname),
1235 init))
1236 tempvardecl_code = code.insertion_point()
1237 self.generate_keyword_list(code)
1238 if profile:
1239 code.put_trace_declarations()
1240 # ----- Extern library function declarations
1241 lenv.generate_library_function_declarations(code)
1242 # ----- GIL acquisition
1243 acquire_gil = self.acquire_gil
1244 if acquire_gil:
1245 env.use_utility_code(force_init_threads_utility_code)
1246 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1247 # ----- Automatic lead-ins for certain special functions
1248 if not lenv.nogil:
1249 code.put_setup_refcount_context(self.entry.name)
1250 if profile:
1251 code.put_trace_call(self.entry.name, self.pos)
1252 if is_getbuffer_slot:
1253 self.getbuffer_init(code)
1254 # ----- Fetch arguments
1255 self.generate_argument_parsing_code(env, code)
1256 # If an argument is assigned to in the body, we must
1257 # incref it to properly keep track of refcounts.
1258 for entry in lenv.arg_entries:
1259 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1260 code.put_var_incref(entry)
1261 # ----- Initialise local variables
1262 for entry in lenv.var_entries:
1263 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1264 code.put_init_var_to_py_none(entry)
1265 # ----- Initialise local buffer auxiliary variables
1266 for entry in lenv.var_entries + lenv.arg_entries:
1267 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1268 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1269 # ----- Check and convert arguments
1270 self.generate_argument_type_tests(code)
1271 # ----- Acquire buffer arguments
1272 for entry in lenv.arg_entries:
1273 if entry.type.is_buffer:
1274 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1275 # ----- Function body
1276 self.body.generate_execution_code(code)
1277 # ----- Default return value
1278 code.putln("")
1279 if self.return_type.is_pyobject:
1280 #if self.return_type.is_extension_type:
1281 # lhs = "(PyObject *)%s" % Naming.retval_cname
1282 #else:
1283 lhs = Naming.retval_cname
1284 code.put_init_to_py_none(lhs, self.return_type)
1285 else:
1286 val = self.return_type.default_value
1287 if val:
1288 code.putln("%s = %s;" % (Naming.retval_cname, val))
1289 # ----- Error cleanup
1290 if code.error_label in code.labels_used:
1291 code.put_goto(code.return_label)
1292 code.put_label(code.error_label)
1293 for cname, type in code.funcstate.all_managed_temps():
1294 code.put_xdecref(cname, type)
1296 # Clean up buffers -- this calls a Python function
1297 # so need to save and restore error state
1298 buffers_present = len(lenv.buffer_entries) > 0
1299 if buffers_present:
1300 code.globalstate.use_utility_code(restore_exception_utility_code)
1301 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1302 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1303 for entry in lenv.buffer_entries:
1304 Buffer.put_release_buffer_code(code, entry)
1305 #code.putln("%s = 0;" % entry.cname)
1306 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1308 err_val = self.error_value()
1309 exc_check = self.caller_will_check_exceptions()
1310 if err_val is not None or exc_check:
1311 # TODO: Fix exception tracing (though currently unused by cProfile).
1312 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1313 # code.put_trace_exception()
1314 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1315 else:
1316 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1317 % self.entry.qualified_name, 0)
1318 code.putln(
1319 '__Pyx_WriteUnraisable("%s");' %
1320 self.entry.qualified_name)
1321 env.use_utility_code(unraisable_exception_utility_code)
1322 env.use_utility_code(restore_exception_utility_code)
1323 default_retval = self.return_type.default_value
1324 if err_val is None and default_retval:
1325 err_val = default_retval
1326 if err_val is not None:
1327 code.putln(
1328 "%s = %s;" % (
1329 Naming.retval_cname,
1330 err_val))
1332 if is_getbuffer_slot:
1333 self.getbuffer_error_cleanup(code)
1335 # If we are using the non-error cleanup section we should
1336 # jump past it if we have an error. The if-test below determine
1337 # whether this section is used.
1338 if buffers_present or is_getbuffer_slot:
1339 code.put_goto(code.return_from_error_cleanup_label)
1342 # ----- Non-error return cleanup
1343 code.put_label(code.return_label)
1344 for entry in lenv.buffer_entries:
1345 if entry.used:
1346 Buffer.put_release_buffer_code(code, entry)
1347 if is_getbuffer_slot:
1348 self.getbuffer_normal_cleanup(code)
1349 # ----- Return cleanup for both error and no-error return
1350 code.put_label(code.return_from_error_cleanup_label)
1351 if not Options.init_local_none:
1352 for entry in lenv.var_entries:
1353 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1354 entry.xdecref_cleanup = 1
1355 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1356 # Decref any increfed args
1357 for entry in lenv.arg_entries:
1358 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1359 code.put_var_decref(entry)
1361 # code.putln("/* TODO: decref scope object */")
1362 # ----- Return
1363 # This code is duplicated in ModuleNode.generate_module_init_func
1364 if not lenv.nogil:
1365 default_retval = self.return_type.default_value
1366 err_val = self.error_value()
1367 if err_val is None and default_retval:
1368 err_val = default_retval
1369 if self.return_type.is_pyobject:
1370 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1372 if self.entry.is_special and self.entry.name == "__hash__":
1373 # Returning -1 for __hash__ is supposed to signal an error
1374 # We do as Python instances and coerce -1 into -2.
1375 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1376 Naming.retval_cname, Naming.retval_cname))
1378 if profile:
1379 if self.return_type.is_pyobject:
1380 code.put_trace_return(Naming.retval_cname)
1381 else:
1382 code.put_trace_return("Py_None")
1383 if not lenv.nogil:
1384 code.put_finish_refcount_context()
1386 if acquire_gil:
1387 code.putln("PyGILState_Release(_save);")
1389 if not self.return_type.is_void:
1390 code.putln("return %s;" % Naming.retval_cname)
1392 code.putln("}")
1393 # ----- Go back and insert temp variable declarations
1394 tempvardecl_code.put_temp_declarations(code.funcstate)
1395 # ----- Python version
1396 code.exit_cfunc_scope()
1397 if self.py_func:
1398 self.py_func.generate_function_definitions(env, code)
1399 self.generate_wrapper_functions(code)
1401 def declare_argument(self, env, arg):
1402 if arg.type.is_void:
1403 error(arg.pos, "Invalid use of 'void'")
1404 elif not arg.type.is_complete() and not arg.type.is_array:
1405 error(arg.pos,
1406 "Argument type '%s' is incomplete" % arg.type)
1407 return env.declare_arg(arg.name, arg.type, arg.pos)
1409 def generate_wrapper_functions(self, code):
1410 pass
1412 def generate_execution_code(self, code):
1413 # Evaluate and store argument default values
1414 for arg in self.args:
1415 default = arg.default
1416 if default:
1417 if not default.is_literal:
1418 default.generate_evaluation_code(code)
1419 default.make_owned_reference(code)
1420 result = default.result_as(arg.type)
1421 code.putln(
1422 "%s = %s;" % (
1423 arg.calculate_default_value_code(code),
1424 result))
1425 if arg.type.is_pyobject:
1426 code.put_giveref(default.result())
1427 default.generate_post_assignment_code(code)
1428 default.free_temps(code)
1429 # For Python class methods, create and store function object
1430 if self.assmt:
1431 self.assmt.generate_execution_code(code)
1433 #
1434 # Special code for the __getbuffer__ function
1435 #
1436 def getbuffer_init(self, code):
1437 info = self.local_scope.arg_entries[1].cname
1438 # Python 3.0 betas have a bug in memoryview which makes it call
1439 # getbuffer with a NULL parameter. For now we work around this;
1440 # the following line should be removed when this bug is fixed.
1441 code.putln("if (%s == NULL) return 0;" % info)
1442 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1443 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1445 def getbuffer_error_cleanup(self, code):
1446 info = self.local_scope.arg_entries[1].cname
1447 code.put_gotref("%s->obj" % info)
1448 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1449 (info, info))
1451 def getbuffer_normal_cleanup(self, code):
1452 info = self.local_scope.arg_entries[1].cname
1453 code.putln("if (%s->obj == Py_None) {" % info)
1454 code.put_gotref("Py_None")
1455 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1456 code.putln("}")
1458 class CFuncDefNode(FuncDefNode):
1459 # C function definition.
1460 #
1461 # modifiers ['inline']
1462 # visibility 'private' or 'public' or 'extern'
1463 # base_type CBaseTypeNode
1464 # declarator CDeclaratorNode
1465 # body StatListNode
1466 # api boolean
1467 # decorators [DecoratorNode] list of decorators
1468 #
1469 # with_gil boolean Acquire GIL around body
1470 # type CFuncType
1471 # py_func wrapper for calling from Python
1472 # overridable whether or not this is a cpdef function
1473 # inline_in_pxd whether this is an inline function in a pxd file
1475 child_attrs = ["base_type", "declarator", "body", "py_func"]
1477 inline_in_pxd = False
1478 decorators = None
1479 directive_locals = {}
1481 def unqualified_name(self):
1482 return self.entry.name
1484 def analyse_declarations(self, env):
1485 self.directive_locals.update(env.directives['locals'])
1486 base_type = self.base_type.analyse(env)
1487 # The 2 here is because we need both function and argument names.
1488 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1489 if not type.is_cfunction:
1490 error(self.pos,
1491 "Suite attached to non-function declaration")
1492 # Remember the actual type according to the function header
1493 # written here, because the type in the symbol table entry
1494 # may be different if we're overriding a C method inherited
1495 # from the base type of an extension type.
1496 self.type = type
1497 type.is_overridable = self.overridable
1498 declarator = self.declarator
1499 while not hasattr(declarator, 'args'):
1500 declarator = declarator.base
1501 self.args = declarator.args
1502 for formal_arg, type_arg in zip(self.args, type.args):
1503 formal_arg.type = type_arg.type
1504 formal_arg.name = type_arg.name
1505 formal_arg.cname = type_arg.cname
1506 name = name_declarator.name
1507 cname = name_declarator.cname
1508 self.entry = env.declare_cfunction(
1509 name, type, self.pos,
1510 cname = cname, visibility = self.visibility,
1511 defining = self.body is not None,
1512 api = self.api, modifiers = self.modifiers)
1513 self.entry.inline_func_in_pxd = self.inline_in_pxd
1514 self.return_type = type.return_type
1516 if self.overridable and not env.is_module_scope:
1517 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1518 # An error will be produced in the cdef function
1519 self.overridable = False
1521 if self.overridable:
1522 import ExprNodes
1523 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1524 self.py_func = DefNode(pos = self.pos,
1525 name = self.entry.name,
1526 args = self.args,
1527 star_arg = None,
1528 starstar_arg = None,
1529 doc = self.doc,
1530 body = py_func_body,
1531 is_wrapper = 1)
1532 self.py_func.is_module_scope = env.is_module_scope
1533 self.py_func.analyse_declarations(env)
1534 self.entry.as_variable = self.py_func.entry
1535 # Reset scope entry the above cfunction
1536 env.entries[name] = self.entry
1537 if not env.is_module_scope or Options.lookup_module_cpdef:
1538 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1539 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1540 self.create_local_scope(env)
1542 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1543 import ExprNodes
1544 args = self.type.args
1545 if omit_optional_args:
1546 args = args[:len(args) - self.type.optional_arg_count]
1547 arg_names = [arg.name for arg in args]
1548 if is_module_scope:
1549 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1550 else:
1551 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1552 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1553 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1554 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)
1555 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1557 def declare_arguments(self, env):
1558 for arg in self.type.args:
1559 if not arg.name:
1560 error(arg.pos, "Missing argument name")
1561 self.declare_argument(env, arg)
1563 def need_gil_acquisition(self, lenv):
1564 return self.type.with_gil
1566 def nogil_check(self, env):
1567 type = self.type
1568 with_gil = type.with_gil
1569 if type.nogil and not with_gil:
1570 if type.return_type.is_pyobject:
1571 error(self.pos,
1572 "Function with Python return type cannot be declared nogil")
1573 for entry in self.local_scope.var_entries:
1574 if entry.type.is_pyobject:
1575 error(self.pos, "Function declared nogil has Python locals or temporaries")
1577 def analyse_expressions(self, env):
1578 self.local_scope.directives = env.directives
1579 if self.py_func is not None:
1580 # this will also analyse the default values
1581 self.py_func.analyse_expressions(env)
1582 else:
1583 self.analyse_default_values(env)
1584 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1586 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1587 arg_decls = []
1588 type = self.type
1589 visibility = self.entry.visibility
1590 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1591 arg_decls.append(arg.declaration_code())
1592 if with_dispatch and self.overridable:
1593 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1594 if type.optional_arg_count and with_opt_args:
1595 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1596 if type.has_varargs:
1597 arg_decls.append("...")
1598 if not arg_decls:
1599 arg_decls = ["void"]
1600 if cname is None:
1601 cname = self.entry.func_cname
1602 entity = type.function_header_code(cname, ', '.join(arg_decls))
1603 if visibility == 'public':
1604 dll_linkage = "DL_EXPORT"
1605 else:
1606 dll_linkage = None
1607 header = self.return_type.declaration_code(entity,
1608 dll_linkage = dll_linkage)
1609 if visibility == 'extern':
1610 storage_class = "%s " % Naming.extern_c_macro
1611 elif visibility == 'public':
1612 storage_class = ""
1613 else:
1614 storage_class = "static "
1615 if 'inline' in self.modifiers:
1616 self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
1617 code.putln("%s%s %s {" % (
1618 storage_class,
1619 ' '.join(self.modifiers).upper(), # macro forms
1620 header))
1622 def generate_argument_declarations(self, env, code):
1623 for arg in self.args:
1624 if arg.default:
1625 result = arg.calculate_default_value_code(code)
1626 code.putln('%s = %s;' % (
1627 arg.type.declaration_code(arg.cname), result))
1629 def generate_keyword_list(self, code):
1630 pass
1632 def generate_argument_parsing_code(self, env, code):
1633 i = 0
1634 if self.type.optional_arg_count:
1635 code.putln('if (%s) {' % Naming.optional_args_cname)
1636 for arg in self.args:
1637 if arg.default:
1638 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1639 declarator = arg.declarator
1640 while not hasattr(declarator, 'name'):
1641 declarator = declarator.base
1642 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1643 i += 1
1644 for _ in range(self.type.optional_arg_count):
1645 code.putln('}')
1646 code.putln('}')
1648 def generate_argument_conversion_code(self, code):
1649 pass
1651 def generate_argument_type_tests(self, code):
1652 # Generate type tests for args whose type in a parent
1653 # class is a supertype of the declared type.
1654 for arg in self.type.args:
1655 if arg.needs_type_test:
1656 self.generate_arg_type_test(arg, code)
1658 def generate_arg_type_test(self, arg, code):
1659 # Generate type test for one argument.
1660 if arg.type.typeobj_is_available():
1661 typeptr_cname = arg.type.typeptr_cname
1662 arg_code = "((PyObject *)%s)" % arg.cname
1663 code.putln(
1664 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1665 arg_code,
1666 typeptr_cname,
1667 not arg.not_none,
1668 arg.name,
1669 type.is_builtin_type,
1670 code.error_goto(arg.pos)))
1671 else:
1672 error(arg.pos, "Cannot test type of extern C class "
1673 "without type object name specification")
1675 def error_value(self):
1676 if self.return_type.is_pyobject:
1677 return "0"
1678 else:
1679 #return None
1680 return self.entry.type.exception_value
1682 def caller_will_check_exceptions(self):
1683 return self.entry.type.exception_check
1685 def generate_wrapper_functions(self, code):
1686 # If the C signature of a function has changed, we need to generate
1687 # wrappers to put in the slots here.
1688 k = 0
1689 entry = self.entry
1690 func_type = entry.type
1691 while entry.prev_entry is not None:
1692 k += 1
1693 entry = entry.prev_entry
1694 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1695 code.putln()
1696 self.generate_function_header(code,
1697 0,
1698 with_dispatch = entry.type.is_overridable,
1699 with_opt_args = entry.type.optional_arg_count,
1700 cname = entry.func_cname)
1701 if not self.return_type.is_void:
1702 code.put('return ')
1703 args = self.type.args
1704 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1705 if entry.type.is_overridable:
1706 arglist.append(Naming.skip_dispatch_cname)
1707 elif func_type.is_overridable:
1708 arglist.append('0')
1709 if entry.type.optional_arg_count:
1710 arglist.append(Naming.optional_args_cname)
1711 elif func_type.optional_arg_count:
1712 arglist.append('NULL')
1713 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1714 code.putln('}')
1717 class PyArgDeclNode(Node):
1718 # Argument which must be a Python object (used
1719 # for * and ** arguments).
1720 #
1721 # name string
1722 # entry Symtab.Entry
1723 child_attrs = []
1726 class DecoratorNode(Node):
1727 # A decorator
1728 #
1729 # decorator NameNode or CallNode
1730 child_attrs = ['decorator']
1733 class DefNode(FuncDefNode):
1734 # A Python function definition.
1735 #
1736 # name string the Python name of the function
1737 # decorators [DecoratorNode] list of decorators
1738 # args [CArgDeclNode] formal arguments
1739 # star_arg PyArgDeclNode or None * argument
1740 # starstar_arg PyArgDeclNode or None ** argument
1741 # doc EncodedString or None
1742 # body StatListNode
1743 #
1744 # The following subnode is constructed internally
1745 # when the def statement is inside a Python class definition.
1746 #
1747 # assmt AssignmentNode Function construction/assignment
1749 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1751 assmt = None
1752 num_kwonly_args = 0
1753 num_required_kw_args = 0
1754 reqd_kw_flags_cname = "0"
1755 is_wrapper = 0
1756 decorators = None
1757 entry = None
1758 acquire_gil = 0
1759 self_in_stararg = 0
1761 def __init__(self, pos, **kwds):
1762 FuncDefNode.__init__(self, pos, **kwds)
1763 k = rk = r = 0
1764 for arg in self.args:
1765 if arg.kw_only:
1766 k += 1
1767 if not arg.default:
1768 rk += 1
1769 if not arg.default:
1770 r += 1
1771 self.num_kwonly_args = k
1772 self.num_required_kw_args = rk
1773 self.num_required_args = r
1775 def as_cfunction(self, cfunc=None, scope=None):
1776 if self.star_arg:
1777 error(self.star_arg.pos, "cdef function cannot have star argument")
1778 if self.starstar_arg:
1779 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1780 if cfunc is None:
1781 cfunc_args = []
1782 for formal_arg in self.args:
1783 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1784 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1785 cname = None,
1786 type = py_object_type,
1787 pos = formal_arg.pos))
1788 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1789 args = cfunc_args,
1790 has_varargs = False,
1791 exception_value = None,
1792 exception_check = False,
1793 nogil = False,
1794 with_gil = False,
1795 is_overridable = True)
1796 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1797 else:
1798 cfunc_type = cfunc.type
1799 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1800 error(self.pos, "wrong number of arguments")
1801 error(cfunc.pos, "previous declaration here")
1802 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1803 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1804 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1805 formal_arg.type = type_arg.type
1806 formal_arg.name_declarator = name_declarator
1807 import ExprNodes
1808 if cfunc_type.exception_value is None:
1809 exception_value = None
1810 else:
1811 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1812 declarator = CFuncDeclaratorNode(self.pos,
1813 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1814 args = self.args,
1815 has_varargs = False,
1816 exception_check = cfunc_type.exception_check,
1817 exception_value = exception_value,
1818 with_gil = cfunc_type.with_gil,
1819 nogil = cfunc_type.nogil)
1820 return CFuncDefNode(self.pos,
1821 modifiers = [],
1822 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1823 declarator = declarator,
1824 body = self.body,
1825 doc = self.doc,
1826 overridable = cfunc_type.is_overridable,
1827 type = cfunc_type,
1828 with_gil = cfunc_type.with_gil,
1829 nogil = cfunc_type.nogil,
1830 visibility = 'private',
1831 api = False,
1832 directive_locals = getattr(cfunc, 'directive_locals', {}))
1834 def analyse_declarations(self, env):
1835 self.is_classmethod = self.is_staticmethod = False
1836 if self.decorators:
1837 for decorator in self.decorators:
1838 func = decorator.decorator
1839 if func.is_name:
1840 self.is_classmethod |= func.name == 'classmethod'
1841 self.is_staticmethod |= func.name == 'staticmethod'
1843 if self.is_classmethod and env.lookup_here('classmethod'):
1844 # classmethod() was overridden - not much we can do here ...
1845 self.is_classmethod = False
1846 if self.is_staticmethod and env.lookup_here('staticmethod'):
1847 # staticmethod() was overridden - not much we can do here ...
1848 self.is_staticmethod = False
1850 self.analyse_argument_types(env)
1851 self.declare_pyfunction(env)
1852 self.analyse_signature(env)
1853 self.return_type = self.entry.signature.return_type()
1854 self.create_local_scope(env)
1856 def analyse_argument_types(self, env):
1857 directive_locals = self.directive_locals = env.directives['locals']
1858 for arg in self.args:
1859 if hasattr(arg, 'name'):
1860 type = arg.type
1861 name_declarator = None
1862 else:
1863 base_type = arg.base_type.analyse(env)
1864 name_declarator, type = \
1865 arg.declarator.analyse(base_type, env)
1866 arg.name = name_declarator.name
1867 if arg.name in directive_locals:
1868 type_node = directive_locals[arg.name]
1869 other_type = type_node.analyse_as_type(env)
1870 if other_type is None:
1871 error(type_node.pos, "Not a type")
1872 elif (type is not PyrexTypes.py_object_type
1873 and not type.same_as(other_type)):
1874 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1875 error(type_node.pos, "Previous declaration here")
1876 else:
1877 type = other_type
1878 if name_declarator and name_declarator.cname:
1879 error(self.pos,
1880 "Python function argument cannot have C name specification")
1881 arg.type = type.as_argument_type()
1882 arg.hdr_type = None
1883 arg.needs_conversion = 0
1884 arg.needs_type_test = 0
1885 arg.is_generic = 1
1886 if arg.not_none and not arg.type.is_extension_type:
1887 error(self.pos,
1888 "Only extension type arguments can have 'not None'")
1890 def analyse_signature(self, env):
1891 any_type_tests_needed = 0
1892 if self.entry.is_special:
1893 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1894 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1895 # Use the simpler calling signature for zero- and one-argument functions.
1896 if self.entry.signature is TypeSlots.pyfunction_signature:
1897 if len(self.args) == 0:
1898 self.entry.signature = TypeSlots.pyfunction_noargs
1899 elif len(self.args) == 1:
1900 if self.args[0].default is None and not self.args[0].kw_only:
1901 self.entry.signature = TypeSlots.pyfunction_onearg
1902 elif self.entry.signature is TypeSlots.pymethod_signature:
1903 if len(self.args) == 1:
1904 self.entry.signature = TypeSlots.unaryfunc
1905 elif len(self.args) == 2:
1906 if self.args[1].default is None and not self.args[1].kw_only:
1907 self.entry.signature = TypeSlots.ibinaryfunc
1909 sig = self.entry.signature
1910 nfixed = sig.num_fixed_args()
1911 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
1912 and len(self.args) == 0 and self.star_arg:
1913 # this is the only case where a diverging number of
1914 # arguments is not an error - when we have no explicit
1915 # 'self' parameter as in method(*args)
1916 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
1917 self.self_in_stararg = 1
1918 nfixed = 0
1920 for i in range(min(nfixed, len(self.args))):
1921 arg = self.args[i]
1922 arg.is_generic = 0
1923 if sig.is_self_arg(i) and not self.is_staticmethod:
1924 if self.is_classmethod:
1925 arg.is_type_arg = 1
1926 arg.hdr_type = arg.type = Builtin.type_type
1927 else:
1928 arg.is_self_arg = 1
1929 arg.hdr_type = arg.type = env.parent_type
1930 arg.needs_conversion = 0
1931 else:
1932 arg.hdr_type = sig.fixed_arg_type(i)
1933 if not arg.type.same_as(arg.hdr_type):
1934 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1935 arg.needs_type_test = 1
1936 any_type_tests_needed = 1
1937 else:
1938 arg.needs_conversion = 1
1939 if arg.needs_conversion:
1940 arg.hdr_cname = Naming.arg_prefix + arg.name
1941 else:
1942 arg.hdr_cname = Naming.var_prefix + arg.name
1944 if nfixed > len(self.args):
1945 self.bad_signature()
1946 return
1947 elif nfixed < len(self.args):
1948 if not sig.has_generic_args:
1949 self.bad_signature()
1950 for arg in self.args:
1951 if arg.is_generic and \
1952 (arg.type.is_extension_type or arg.type.is_builtin_type):
1953 arg.needs_type_test = 1
1954 any_type_tests_needed = 1
1955 if any_type_tests_needed:
1956 env.use_utility_code(arg_type_test_utility_code)
1958 def bad_signature(self):
1959 sig = self.entry.signature
1960 expected_str = "%d" % sig.num_fixed_args()
1961 if sig.has_generic_args:
1962 expected_str = expected_str + " or more"
1963 name = self.name
1964 if name.startswith("__") and name.endswith("__"):
1965 desc = "Special method"
1966 else:
1967 desc = "Method"
1968 error(self.pos,
1969 "%s %s has wrong number of arguments "
1970 "(%d declared, %s expected)" % (
1971 desc, self.name, len(self.args), expected_str))
1973 def signature_has_nongeneric_args(self):
1974 argcount = len(self.args)
1975 if argcount == 0 or (
1976 argcount == 1 and (self.args[0].is_self_arg or
1977 self.args[0].is_type_arg)):
1978 return 0
1979 return 1
1981 def signature_has_generic_args(self):
1982 return self.entry.signature.has_generic_args
1984 def declare_pyfunction(self, env):
1985 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1986 name = self.name
1987 entry = env.lookup_here(self.name)
1988 if entry and entry.type.is_cfunction and not self.is_wrapper:
1989 warning(self.pos, "Overriding cdef method with def method.", 5)
1990 entry = env.declare_pyfunction(self.name, self.pos)
1991 self.entry = entry
1992 prefix = env.scope_prefix
1993 entry.func_cname = \
1994 Naming.pyfunc_prefix + prefix + name
1995 entry.pymethdef_cname = \
1996 Naming.pymethdef_prefix + prefix + name
1997 if Options.docstrings:
1998 entry.doc = embed_position(self.pos, self.doc)
1999 entry.doc_cname = \
2000 Naming.funcdoc_prefix + prefix + name
2001 else:
2002 entry.doc = None
2004 def declare_arguments(self, env):
2005 for arg in self.args:
2006 if not arg.name:
2007 error(arg.pos, "Missing argument name")
2008 if arg.needs_conversion:
2009 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
2010 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
2011 env.control_flow.set_state((), (arg.name, 'initalized'), True)
2012 if arg.type.is_pyobject:
2013 arg.entry.init = "0"
2014 arg.entry.init_to_none = 0
2015 else:
2016 arg.entry = self.declare_argument(env, arg)
2017 arg.entry.used = 1
2018 arg.entry.is_self_arg = arg.is_self_arg
2019 if arg.hdr_type:
2020 if arg.is_self_arg or arg.is_type_arg or \
2021 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
2022 arg.entry.is_declared_generic = 1
2023 self.declare_python_arg(env, self.star_arg)
2024 self.declare_python_arg(env, self.starstar_arg)
2026 def declare_python_arg(self, env, arg):
2027 if arg:
2028 if env.directives['infer_types'] != False:
2029 type = PyrexTypes.unspecified_type
2030 else:
2031 type = py_object_type
2032 entry = env.declare_var(arg.name, type, arg.pos)
2033 entry.used = 1
2034 entry.init = "0"
2035 entry.init_to_none = 0
2036 entry.xdecref_cleanup = 1
2037 arg.entry = entry
2038 env.control_flow.set_state((), (arg.name, 'initalized'), True)
2040 def analyse_expressions(self, env):
2041 self.local_scope.directives = env.directives
2042 self.analyse_default_values(env)
2043 if env.is_py_class_scope:
2044 self.synthesize_assignment_node(env)
2046 def synthesize_assignment_node(self, env):
2047 import ExprNodes
2048 self.assmt = SingleAssignmentNode(self.pos,
2049 lhs = ExprNodes.NameNode(self.pos, name = self.name),
2050 rhs = ExprNodes.UnboundMethodNode(self.pos,
2051 function = ExprNodes.PyCFunctionNode(self.pos,
2052 pymethdef_cname = self.entry.pymethdef_cname)))
2053 self.assmt.analyse_declarations(env)
2054 self.assmt.analyse_expressions(env)
2056 def generate_function_header(self, code, with_pymethdef, proto_only=0):
2057 arg_code_list = []
2058 sig = self.entry.signature
2059 if sig.has_dummy_arg or self.self_in_stararg:
2060 arg_code_list.append(
2061 "PyObject *%s" % Naming.self_cname)
2062 for arg in self.args:
2063 if not arg.is_generic:
2064 if arg.is_self_arg or arg.is_type_arg:
2065 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
2066 else:
2067 arg_code_list.append(
2068 arg.hdr_type.declaration_code(arg.hdr_cname))
2069 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
2070 arg_code_list.append("PyObject *unused")
2071 if sig.has_generic_args:
2072 arg_code_list.append(
2073 "PyObject *%s, PyObject *%s"
2074 % (Naming.args_cname, Naming.kwds_cname))
2075 arg_code = ", ".join(arg_code_list)
2076 dc = self.return_type.declaration_code(self.entry.func_cname)
2077 header = "static %s(%s)" % (dc, arg_code)
2078 code.putln("%s; /*proto*/" % header)
2079 if proto_only:
2080 return
2081 if self.entry.doc and Options.docstrings:
2082 docstr = self.entry.doc
2083 if docstr.is_unicode:
2084 docstr = docstr.utf8encode()
2085 code.putln(
2086 'static char %s[] = "%s";' % (
2087 self.entry.doc_cname,
2088 split_string_literal(escape_byte_string(docstr))))
2089 if with_pymethdef:
2090 code.put(
2091 "static PyMethodDef %s = " %
2092 self.entry.pymethdef_cname)
2093 code.put_pymethoddef(self.entry, ";")
2094 code.putln("%s {" % header)
2096 def generate_argument_declarations(self, env, code):
2097 for arg in self.args:
2098 if arg.is_generic: # or arg.needs_conversion:
2099 if arg.needs_conversion:
2100 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
2101 else:
2102 code.put_var_declaration(arg.entry)
2104 def generate_keyword_list(self, code):
2105 if self.signature_has_generic_args() and \
2106 self.signature_has_nongeneric_args():
2107 code.put(
2108 "static PyObject **%s[] = {" %
2109 Naming.pykwdlist_cname)
2110 for arg in self.args:
2111 if arg.is_generic:
2112 pystring_cname = code.intern_identifier(arg.name)
2113 code.put('&%s,' % pystring_cname)
2114 code.putln("0};")
2116 def generate_argument_parsing_code(self, env, code):
2117 # Generate PyArg_ParseTuple call for generic
2118 # arguments, if any.
2119 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
2120 # get rid of unused argument warning
2121 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
2123 old_error_label = code.new_error_label()
2124 our_error_label = code.error_label
2125 end_label = code.new_label("argument_unpacking_done")
2127 has_kwonly_args = self.num_kwonly_args > 0
2128 has_star_or_kw_args = self.star_arg is not None \
2129 or self.starstar_arg is not None or has_kwonly_args
2131 for arg in self.args:
2132 if not arg.type.is_pyobject:
2133 done = arg.type.create_from_py_utility_code(env)
2134 if not done: pass # will fail later
2136 if not self.signature_has_generic_args():
2137 if has_star_or_kw_args:
2138 error(self.pos, "This method cannot have * or keyword arguments")
2139 self.generate_argument_conversion_code(code)
2141 elif not self.signature_has_nongeneric_args():
2142 # func(*args) or func(**kw) or func(*args, **kw)
2143 self.generate_stararg_copy_code(code)
2145 else:
2146 positional_args = []
2147 kw_only_args = []
2148 for arg in self.args:
2149 arg_entry = arg.entry
2150 if arg.is_generic:
2151 if arg.default:
2152 if not arg.is_self_arg and not arg.is_type_arg:
2153 if arg.kw_only:
2154 kw_only_args.append(arg)
2155 else:
2156 positional_args.append(arg)
2157 elif arg.kw_only:
2158 kw_only_args.append(arg)
2159 elif not arg.is_self_arg and not arg.is_type_arg:
2160 positional_args.append(arg)
2162 self.generate_tuple_and_keyword_parsing_code(
2163 positional_args, kw_only_args, end_label, code)
2165 code.error_label = old_error_label
2166 if code.label_used(our_error_label):
2167 if not code.label_used(end_label):
2168 code.put_goto(end_label)
2169 code.put_label(our_error_label)
2170 if has_star_or_kw_args:
2171 self.generate_arg_decref(self.star_arg, code)
2172 if self.starstar_arg:
2173 if self.starstar_arg.entry.xdecref_cleanup:
2174 code.put_var_xdecref(self.starstar_arg.entry)
2175 else:
2176 code.put_var_decref(self.starstar_arg.entry)
2177 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2178 code.putln("return %s;" % self.error_value())
2179 if code.label_used(end_label):
2180 code.put_label(end_label)
2182 def generate_arg_assignment(self, arg, item, code):
2183 if arg.type.is_pyobject:
2184 if arg.is_generic:
2185 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2186 code.putln("%s = %s;" % (arg.entry.cname, item))
2187 else:
2188 func = arg.type.from_py_function
2189 if func:
2190 code.putln("%s = %s(%s); %s" % (
2191 arg.entry.cname,
2192 func,
2193 item,
2194 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2195 else:
2196 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2198 def generate_arg_xdecref(self, arg, code):
2199 if arg:
2200 code.put_var_xdecref(arg.entry)
2202 def generate_arg_decref(self, arg, code):
2203 if arg:
2204 code.put_var_decref(arg.entry)
2206 def generate_stararg_copy_code(self, code):
2207 if not self.star_arg:
2208 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2209 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2210 Naming.args_cname)
2211 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2212 self.name, Naming.args_cname, self.error_value()))
2213 code.putln("}")
2215 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2217 if self.starstar_arg:
2218 if self.star_arg:
2219 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2220 else:
2221 kwarg_check = "%s" % Naming.kwds_cname
2222 else:
2223 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2224 Naming.kwds_cname, Naming.kwds_cname)
2225 code.putln(
2226 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2227 kwarg_check, Naming.kwds_cname, self.name,
2228 bool(self.starstar_arg), self.error_value()))
2230 if self.starstar_arg:
2231 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2232 self.starstar_arg.entry.cname,
2233 Naming.kwds_cname,
2234 Naming.kwds_cname))
2235 code.putln("if (unlikely(!%s)) return %s;" % (
2236 self.starstar_arg.entry.cname, self.error_value()))
2237 self.starstar_arg.entry.xdecref_cleanup = 0
2238 code.put_gotref(self.starstar_arg.entry.cname)
2240 if self.self_in_stararg:
2241 # need to create a new tuple with 'self' inserted as first item
2242 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2243 self.star_arg.entry.cname,
2244 Naming.args_cname,
2245 self.star_arg.entry.cname))
2246 if self.starstar_arg:
2247 code.putln("{")
2248 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2249 code.putln("return %s;" % self.error_value())
2250 code.putln("}")
2251 else:
2252 code.putln("return %s;" % self.error_value())
2253 code.put_gotref(self.star_arg.entry.cname)
2254 code.put_incref(Naming.self_cname, py_object_type)
2255 code.put_giveref(Naming.self_cname)
2256 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2257 self.star_arg.entry.cname, Naming.self_cname))
2258 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2259 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2260 temp, temp, Naming.args_cname, temp))
2261 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2262 Naming.args_cname, temp))
2263 code.put_incref("item", py_object_type)
2264 code.put_giveref("item")
2265 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2266 self.star_arg.entry.cname, temp))
2267 code.putln("}")
2268 code.funcstate.release_temp(temp)
2269 self.star_arg.entry.xdecref_cleanup = 0
2270 elif self.star_arg:
2271 code.put_incref(Naming.args_cname, py_object_type)
2272 code.putln("%s = %s;" % (
2273 self.star_arg.entry.cname,
2274 Naming.args_cname))
2275 self.star_arg.entry.xdecref_cleanup = 0
2277 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2278 kw_only_args, success_label, code):
2279 argtuple_error_label = code.new_label("argtuple_error")
2281 min_positional_args = self.num_required_args - self.num_required_kw_args
2282 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2283 min_positional_args -= 1
2284 max_positional_args = len(positional_args)
2285 has_fixed_positional_count = not self.star_arg and \
2286 min_positional_args == max_positional_args
2288 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2289 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2290 if self.num_required_kw_args:
2291 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2293 if self.starstar_arg or self.star_arg:
2294 self.generate_stararg_init_code(max_positional_args, code)
2296 # --- optimised code when we receive keyword arguments
2297 if self.num_required_kw_args:
2298 likely_hint = "likely"
2299 else:
2300 likely_hint = "unlikely"
2301 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2302 self.generate_keyword_unpacking_code(
2303 min_positional_args, max_positional_args,
2304 has_fixed_positional_count,
2305 positional_args, kw_only_args, argtuple_error_label, code)
2307 # --- optimised code when we do not receive any keyword arguments
2308 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2309 # Python raises arg tuple related errors first, so we must
2310 # check the length here
2311 if min_positional_args == max_positional_args and not self.star_arg:
2312 compare = '!='
2313 else:
2314 compare = '<'
2315 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2316 Naming.args_cname, compare, min_positional_args))
2317 code.put_goto(argtuple_error_label)
2319 if self.num_required_kw_args:
2320 # pure error case: keywords required but not passed
2321 if max_positional_args > min_positional_args and not self.star_arg:
2322 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2323 Naming.args_cname, max_positional_args))
2324 code.put_goto(argtuple_error_label)
2325 code.putln('} else {')
2326 for i, arg in enumerate(kw_only_args):
2327 if not arg.default:
2328 pystring_cname = code.intern_identifier(arg.name)
2329 # required keyword-only argument missing
2330 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2331 self.name,
2332 pystring_cname))
2333 code.putln(code.error_goto(self.pos))
2334 break
2336 elif min_positional_args == max_positional_args:
2337 # parse the exact number of positional arguments from the
2338 # args tuple
2339 code.putln('} else {')
2340 for i, arg in enumerate(positional_args):
2341 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2342 self.generate_arg_assignment(arg, item, code)
2343 self.generate_arg_default_assignments(code)
2345 else:
2346 # parse the positional arguments from the variable length
2347 # args tuple
2348 code.putln('} else {')
2349 self.generate_arg_default_assignments(code)
2350 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2351 if self.star_arg:
2352 code.putln('default:')
2353 reversed_args = list(enumerate(positional_args))[::-1]
2354 for i, arg in reversed_args:
2355 if i >= min_positional_args-1:
2356 if min_positional_args > 1:
2357 code.putln('case %2d:' % (i+1)) # pure code beautification
2358 else:
2359 code.put('case %2d: ' % (i+1))
2360 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2361 self.generate_arg_assignment(arg, item, code)
2362 if min_positional_args == 0:
2363 code.put('case 0: ')
2364 code.putln('break;')
2365 if self.star_arg:
2366 if min_positional_args:
2367 for i in range(min_positional_args-1, -1, -1):
2368 code.putln('case %2d:' % i)
2369 code.put_goto(argtuple_error_label)
2370 else:
2371 code.put('default: ')
2372 code.put_goto(argtuple_error_label)
2373 code.putln('}')
2375 code.putln('}')
2377 if code.label_used(argtuple_error_label):
2378 code.put_goto(success_label)
2379 code.put_label(argtuple_error_label)
2380 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2381 self.name, has_fixed_positional_count,
2382 min_positional_args, max_positional_args,
2383 Naming.args_cname))
2384 code.putln(code.error_goto(self.pos))
2386 def generate_arg_default_assignments(self, code):
2387 for arg in self.args:
2388 if arg.is_generic and arg.default:
2389 code.putln(
2390 "%s = %s;" % (
2391 arg.entry.cname,
2392 arg.calculate_default_value_code(code)))
2394 def generate_stararg_init_code(self, max_positional_args, code):
2395 if self.starstar_arg:
2396 self.starstar_arg.entry.xdecref_cleanup = 0
2397 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2398 self.starstar_arg.entry.cname,
2399 self.starstar_arg.entry.cname,
2400 self.error_value()))
2401 code.put_gotref(self.starstar_arg.entry.cname)
2402 if self.star_arg:
2403 self.star_arg.entry.xdecref_cleanup = 0
2404 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2405 Naming.args_cname,
2406 max_positional_args))
2407 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2408 self.star_arg.entry.cname, Naming.args_cname,
2409 max_positional_args, Naming.args_cname))
2410 code.put_gotref(self.star_arg.entry.cname)
2411 if self.starstar_arg:
2412 code.putln("")
2413 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2414 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2415 code.putln('return %s;' % self.error_value())
2416 code.putln('}')
2417 else:
2418 code.putln("if (unlikely(!%s)) return %s;" % (
2419 self.star_arg.entry.cname, self.error_value()))
2420 code.putln('} else {')
2421 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2422 code.put_incref(Naming.empty_tuple, py_object_type)
2423 code.putln('}')
2425 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2426 has_fixed_positional_count, positional_args,
2427 kw_only_args, argtuple_error_label, code):
2428 all_args = tuple(positional_args) + tuple(kw_only_args)
2429 max_args = len(all_args)
2431 default_args = []
2432 for i, arg in enumerate(all_args):
2433 if arg.default and arg.type.is_pyobject:
2434 default_value = arg.calculate_default_value_code(code)
2435 if arg.type is not PyrexTypes.py_object_type:
2436 default_value = "(PyObject*)"+default_value
2437 default_args.append((i, default_value))
2439 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2440 Naming.kwds_cname)
2441 # it looks funny to separate the init-to-0 from setting the
2442 # default value, but C89 needs this
2443 code.putln("PyObject* values[%d] = {%s};" % (
2444 max_args, ','.join('0'*max_args)))
2445 for i, default_value in default_args:
2446 code.putln('values[%d] = %s;' % (i, default_value))
2448 # parse the tuple and check that it's not too long
2449 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2450 if self.star_arg:
2451 code.putln('default:')
2452 for i in range(max_positional_args-1, -1, -1):
2453 code.put('case %2d: ' % (i+1))
2454 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2455 i, Naming.args_cname, i))
2456 code.putln('case 0: break;')
2457 if not self.star_arg:
2458 code.put('default: ') # more arguments than allowed
2459 code.put_goto(argtuple_error_label)
2460 code.putln('}')
2462 # now fill up the positional/required arguments with values
2463 # from the kw dict
2464 if self.num_required_args or max_positional_args > 0:
2465 last_required_arg = -1
2466 for i, arg in enumerate(all_args):
2467 if not arg.default:
2468 last_required_arg = i
2469 if last_required_arg < max_positional_args:
2470 last_required_arg = max_positional_args-1
2471 num_required_args = self.num_required_args
2472 if max_positional_args > 0:
2473 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2474 for i, arg in enumerate(all_args[:last_required_arg+1]):
2475 if max_positional_args > 0 and i <= max_positional_args:
2476 if self.star_arg and i == max_positional_args:
2477 code.putln('default:')
2478 else:
2479 code.putln('case %2d:' % i)
2480 pystring_cname = code.intern_identifier(arg.name)
2481 if arg.default:
2482 if arg.kw_only:
2483 # handled separately below
2484 continue
2485 code.putln('if (kw_args > %d) {' % num_required_args)
2486 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2487 Naming.kwds_cname, pystring_cname))
2488 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2489 code.putln('}')
2490 else:
2491 num_required_args -= 1
2492 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2493 i, Naming.kwds_cname, pystring_cname))
2494 code.putln('if (likely(values[%d])) kw_args--;' % i);
2495 if i < min_positional_args:
2496 if i == 0:
2497 # special case: we know arg 0 is missing
2498 code.put('else ')
2499 code.put_goto(argtuple_error_label)
2500 else:
2501 # print the correct number of values (args or
2502 # kwargs) that were passed into positional
2503 # arguments up to this point
2504 code.putln('else {')
2505 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2506 self.name, has_fixed_positional_count,
2507 min_positional_args, max_positional_args, i))
2508 code.putln(code.error_goto(self.pos))
2509 code.putln('}')
2510 elif arg.kw_only:
2511 code.putln('else {')
2512 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2513 self.name, pystring_cname))
2514 code.putln(code.error_goto(self.pos))
2515 code.putln('}')
2516 if max_positional_args > 0:
2517 code.putln('}')
2519 if kw_only_args and not self.starstar_arg:
2520 # unpack optional keyword-only arguments
2521 # checking for interned strings in a dict is faster than iterating
2522 # but it's too likely that we must iterate if we expect **kwargs
2523 optional_args = []
2524 for i, arg in enumerate(all_args[max_positional_args:]):
2525 if not arg.kw_only or not arg.default:
2526 continue
2527 optional_args.append((i+max_positional_args, arg))
2528 if optional_args:
2529 # this mimics an unrolled loop so that we can "break" out of it
2530 code.putln('while (kw_args > 0) {')
2531 code.putln('PyObject* value;')
2532 for i, arg in optional_args:
2533 pystring_cname = code.intern_identifier(arg.name)
2534 code.putln(
2535 'value = PyDict_GetItem(%s, %s);' % (
2536 Naming.kwds_cname, pystring_cname))
2537 code.putln(
2538 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2539 code.putln('break;')
2540 code.putln('}')
2542 code.putln('if (unlikely(kw_args > 0)) {')
2543 # non-positional/-required kw args left in dict: default args,
2544 # kw-only args, **kwargs or error
2545 #
2546 # This is sort of a catch-all: except for checking required
2547 # arguments, this will always do the right thing for unpacking
2548 # keyword arguments, so that we can concentrate on optimising
2549 # common cases above.
2550 if max_positional_args == 0:
2551 pos_arg_count = "0"
2552 elif self.star_arg:
2553 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2554 Naming.args_cname, max_positional_args,
2555 Naming.args_cname, max_positional_args))
2556 pos_arg_count = "used_pos_args"
2557 else:
2558 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2559 code.globalstate.use_utility_code(parse_keywords_utility_code)
2560 code.put(
2561 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2562 Naming.kwds_cname,
2563 Naming.pykwdlist_cname,
2564 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2565 pos_arg_count,
2566 self.name))
2567 code.putln(code.error_goto(self.pos))
2568 code.putln('}')
2570 # convert arg values to their final type and assign them
2571 for i, arg in enumerate(all_args):
2572 if arg.default and not arg.type.is_pyobject:
2573 code.putln("if (values[%d]) {" % i)
2574 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2575 if arg.default and not arg.type.is_pyobject:
2576 code.putln('} else {')
2577 code.putln(
2578 "%s = %s;" % (
2579 arg.entry.cname,
2580 arg.calculate_default_value_code(code)))
2581 code.putln('}')
2583 def generate_argument_conversion_code(self, code):
2584 # Generate code to convert arguments from
2585 # signature type to declared type, if needed.
2586 for arg in self.args:
2587 if arg.needs_conversion:
2588 self.generate_arg_conversion(arg, code)
2590 def generate_arg_conversion(self, arg, code):
2591 # Generate conversion code for one argument.
2592 old_type = arg.hdr_type
2593 new_type = arg.type
2594 if old_type.is_pyobject:
2595 if arg.default:
2596 code.putln("if (%s) {" % arg.hdr_cname)
2597 else:
2598 code.putln("assert(%s); {" % arg.hdr_cname)
2599 self.generate_arg_conversion_from_pyobject(arg, code)
2600 code.putln("}")
2601 elif new_type.is_pyobject:
2602 self.generate_arg_conversion_to_pyobject(arg, code)
2603 else:
2604 if new_type.assignable_from(old_type):
2605 code.putln(
2606 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2607 else:
2608 error(arg.pos,
2609 "Cannot convert 1 argument from '%s' to '%s'" %
2610 (old_type, new_type))
2612 def generate_arg_conversion_from_pyobject(self, arg, code):
2613 new_type = arg.type
2614 func = new_type.from_py_function
2615 # copied from CoerceFromPyTypeNode
2616 if func:
2617 code.putln("%s = %s(%s); %s" % (
2618 arg.entry.cname,
2619 func,
2620 arg.hdr_cname,
2621 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2622 else:
2623 error(arg.pos,
2624 "Cannot convert Python object argument to type '%s'"
2625 % new_type)
2627 def generate_arg_conversion_to_pyobject(self, arg, code):
2628 old_type = arg.hdr_type
2629 func = old_type.to_py_function
2630 if func:
2631 code.putln("%s = %s(%s); %s" % (
2632 arg.entry.cname,
2633 func,
2634 arg.hdr_cname,
2635 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2636 code.put_var_gotref(arg.entry)
2637 else:
2638 error(arg.pos,
2639 "Cannot convert argument of type '%s' to Python object"
2640 % old_type)
2642 def generate_argument_type_tests(self, code):
2643 # Generate type tests for args whose signature
2644 # type is PyObject * and whose declared type is
2645 # a subtype thereof.
2646 for arg in self.args:
2647 if arg.needs_type_test:
2648 self.generate_arg_type_test(arg, code)
2650 def generate_arg_type_test(self, arg, code):
2651 # Generate type test for one argument.
2652 if arg.type.typeobj_is_available():
2653 typeptr_cname = arg.type.typeptr_cname
2654 arg_code = "((PyObject *)%s)" % arg.entry.cname
2655 code.putln(
2656 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2657 arg_code,
2658 typeptr_cname,
2659 not arg.not_none,
2660 arg.name,
2661 arg.type.is_builtin_type,
2662 code.error_goto(arg.pos)))
2663 else:
2664 error(arg.pos, "Cannot test type of extern C class "
2665 "without type object name specification")
2667 def error_value(self):
2668 return self.entry.signature.error_value
2670 def caller_will_check_exceptions(self):
2671 return 1
2673 class OverrideCheckNode(StatNode):
2674 # A Node for dispatching to the def method if it
2675 # is overriden.
2676 #
2677 # py_func
2678 #
2679 # args
2680 # func_temp
2681 # body
2683 child_attrs = ['body']
2685 body = None
2687 def analyse_expressions(self, env):
2688 self.args = env.arg_entries
2689 if self.py_func.is_module_scope:
2690 first_arg = 0
2691 else:
2692 first_arg = 1
2693 import ExprNodes
2694 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2695 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2696 call_node = ExprNodes.SimpleCallNode(self.pos,
2697 function=self.func_node,
2698 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2699 self.body = ReturnStatNode(self.pos, value=call_node)
2700 self.body.analyse_expressions(env)
2702 def generate_execution_code(self, code):
2703 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2704 # Check to see if we are an extension type
2705 if self.py_func.is_module_scope:
2706 self_arg = "((PyObject *)%s)" % Naming.module_cname
2707 else:
2708 self_arg = "((PyObject *)%s)" % self.args[0].cname
2709 code.putln("/* Check if called by wrapper */")
2710 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2711 code.putln("/* Check if overriden in Python */")
2712 if self.py_func.is_module_scope:
2713 code.putln("else {")
2714 else:
2715 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2716 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2717 self.func_node.set_cname(func_node_temp)
2718 # need to get attribute manually--scope would return cdef method
2719 err = code.error_goto_if_null(func_node_temp, self.pos)
2720 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2721 func_node_temp, self_arg, interned_attr_cname, err))
2722 code.put_gotref(func_node_temp)
2723 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2724 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2725 func_node_temp, self.py_func.entry.func_cname)
2726 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2727 self.body.generate_execution_code(code)
2728 code.putln("}")
2729 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2730 code.funcstate.release_temp(func_node_temp)
2731 code.putln("}")
2733 class ClassDefNode(StatNode, BlockNode):
2734 pass
2736 class PyClassDefNode(ClassDefNode):
2737 # A Python class definition.
2738 #
2739 # name EncodedString Name of the class
2740 # doc string or None
2741 # body StatNode Attribute definition code
2742 # entry Symtab.Entry
2743 # scope PyClassScope
2744 # decorators [DecoratorNode] list of decorators or None
2745 #
2746 # The following subnodes are constructed internally:
2747 #
2748 # dict DictNode Class dictionary
2749 # classobj ClassNode Class object
2750 # target NameNode Variable to assign class object to
2752 child_attrs = ["body", "dict", "classobj", "target"]
2753 decorators = None
2755 def __init__(self, pos, name, bases, doc, body, decorators = None):
2756 StatNode.__init__(self, pos)
2757 self.name = name
2758 self.doc = doc
2759 self.body = body
2760 self.decorators = decorators
2761 import ExprNodes
2762 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2763 if self.doc and Options.docstrings:
2764 doc = embed_position(self.pos, self.doc)
2765 # FIXME: correct string node?
2766 doc_node = ExprNodes.StringNode(pos, value = doc)
2767 else:
2768 doc_node = None
2769 self.classobj = ExprNodes.ClassNode(pos, name = name,
2770 bases = bases, dict = self.dict, doc = doc_node)
2771 self.target = ExprNodes.NameNode(pos, name = name)
2773 def as_cclass(self):
2774 """
2775 Return this node as if it were declared as an extension class
2776 """
2777 bases = self.classobj.bases.args
2778 if len(bases) == 0:
2779 base_class_name = None
2780 base_class_module = None
2781 elif len(bases) == 1:
2782 base = bases[0]
2783 path = []
2784 from ExprNodes import AttributeNode, NameNode
2785 while isinstance(base, AttributeNode):
2786 path.insert(0, base.attribute)
2787 base = base.obj
2788 if isinstance(base, NameNode):
2789 path.insert(0, base.name)
2790 base_class_name = path[-1]
2791 if len(path) > 1:
2792 base_class_module = u'.'.join(path[:-1])
2793 else:
2794 base_class_module = None
2795 else:
2796 error(self.classobj.bases.args.pos, "Invalid base class")
2797 else:
2798 error(self.classobj.bases.args.pos, "C class may only have one base class")
2799 return None
2801 return CClassDefNode(self.pos,
2802 visibility = 'private',
2803 module_name = None,
2804 class_name = self.name,
2805 base_class_module = base_class_module,
2806 base_class_name = base_class_name,
2807 decorators = self.decorators,
2808 body = self.body,
2809 in_pxd = False,
2810 doc = self.doc)
2812 def create_scope(self, env):
2813 genv = env
2814 while env.is_py_class_scope or env.is_c_class_scope:
2815 env = env.outer_scope
2816 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2817 return cenv
2819 def analyse_declarations(self, env):
2820 self.target.analyse_target_declaration(env)
2821 cenv = self.create_scope(env)
2822 cenv.directives = env.directives
2823 cenv.class_obj_cname = self.target.entry.cname
2824 self.body.analyse_declarations(cenv)
2826 def analyse_expressions(self, env):
2827 self.dict.analyse_expressions(env)
2828 self.classobj.analyse_expressions(env)
2829 genv = env.global_scope()
2830 cenv = self.scope
2831 self.body.analyse_expressions(cenv)
2832 self.target.analyse_target_expression(env, self.classobj)
2834 def generate_function_definitions(self, env, code):
2835 self.body.generate_function_definitions(self.scope, code)
2837 def generate_execution_code(self, code):
2838 code.pyclass_stack.append(self)
2839 cenv = self.scope
2840 self.dict.generate_evaluation_code(code)
2841 self.classobj.generate_evaluation_code(code)
2842 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2843 self.body.generate_execution_code(code)
2844 self.target.generate_assignment_code(self.classobj, code)
2845 self.dict.generate_disposal_code(code)
2846 self.dict.free_temps(code)
2847 code.pyclass_stack.pop()
2850 class CClassDefNode(ClassDefNode):
2851 # An extension type definition.
2852 #
2853 # visibility 'private' or 'public' or 'extern'
2854 # typedef_flag boolean
2855 # api boolean
2856 # module_name string or None For import of extern type objects
2857 # class_name string Unqualified name of class
2858 # as_name string or None Name to declare as in this scope
2859 # base_class_module string or None Module containing the base class
2860 # base_class_name string or None Name of the base class
2861 # objstruct_name string or None Specified C name of object struct
2862 # typeobj_name string or None Specified C name of type object
2863 # in_pxd boolean Is in a .pxd file
2864 # decorators [DecoratorNode] list of decorators or None
2865 # doc string or None
2866 # body StatNode or None
2867 # entry Symtab.Entry
2868 # base_type PyExtensionType or None
2869 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2870 # buffer_defaults_pos
2872 child_attrs = ["body"]
2873 buffer_defaults_node = None
2874 buffer_defaults_pos = None
2875 typedef_flag = False
2876 api = False
2877 objstruct_name = None
2878 typeobj_name = None
2879 decorators = None
2881 def analyse_declarations(self, env):
2882 #print "CClassDefNode.analyse_declarations:", self.class_name
2883 #print "...visibility =", self.visibility
2884 #print "...module_name =", self.module_name
2886 import Buffer
2887 if self.buffer_defaults_node:
2888 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2889 env, [], self.buffer_defaults_node,
2890 need_complete=False)
2891 else:
2892 buffer_defaults = None
2894 if env.in_cinclude and not self.objstruct_name:
2895 error(self.pos, "Object struct name specification required for "
2896 "C class defined in 'extern from' block")
2897 self.base_type = None
2898 # Now that module imports are cached, we need to
2899 # import the modules for extern classes.
2900 if self.module_name:
2901 self.module = None
2902 for module in env.cimported_modules:
2903 if module.name == self.module_name:
2904 self.module = module
2905 if self.module is None:
2906 self.module = ModuleScope(self.module_name, None, env.context)
2907 self.module.has_extern_class = 1
2908 env.add_imported_module(self.module)
2910 if self.base_class_name:
2911 if self.base_class_module:
2912 base_class_scope = env.find_module(self.base_class_module, self.pos)
2913 else:
2914 base_class_scope = env
2915 if self.base_class_name == 'object':
2916 # extension classes are special and don't need to inherit from object
2917 if base_class_scope is None or base_class_scope.lookup('object') is None:
2918 self.base_class_name = None
2919 self.base_class_module = None
2920 base_class_scope = None
2921 if base_class_scope:
2922 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2923 if base_class_entry:
2924 if not base_class_entry.is_type:
2925 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2926 elif not base_class_entry.type.is_extension_type:
2927 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2928 elif not base_class_entry.type.is_complete():
2929 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2930 else:
2931 self.base_type = base_class_entry.type
2932 has_body = self.body is not None
2933 if self.module_name and self.visibility != 'extern':
2934 module_path = self.module_name.split(".")
2935 home_scope = env.find_imported_module(module_path, self.pos)
2936 if not home_scope:
2937 return
2938 else:
2939 home_scope = env
2941 if self.visibility == 'extern':
2942 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2943 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2945 self.entry = home_scope.declare_c_class(
2946 name = self.class_name,
2947 pos = self.pos,
2948 defining = has_body and self.in_pxd,
2949 implementing = has_body and not self.in_pxd,
2950 module_name = self.module_name,
2951 base_type = self.base_type,
2952 objstruct_cname = self.objstruct_name,
2953 typeobj_cname = self.typeobj_name,
2954 visibility = self.visibility,
2955 typedef_flag = self.typedef_flag,
2956 api = self.api,
2957 buffer_defaults = buffer_defaults)
2958 if home_scope is not env and self.visibility == 'extern':
2959 env.add_imported_entry(self.class_name, self.entry, pos)
2960 self.scope = scope = self.entry.type.scope
2961 if scope is not None:
2962 scope.directives = env.directives
2964 if self.doc and Options.docstrings:
2965 scope.doc = embed_position(self.pos, self.doc)
2967 if has_body:
2968 self.body.analyse_declarations(scope)
2969 if self.in_pxd:
2970 scope.defined = 1
2971 else:
2972 scope.implemented = 1
2973 env.allocate_vtable_names(self.entry)
2975 def analyse_expressions(self, env):
2976 if self.body:
2977 scope = self.entry.type.scope
2978 self.body.analyse_expressions(scope)
2980 def generate_function_definitions(self, env, code):
2981 if self.body:
2982 self.body.generate_function_definitions(
2983 self.entry.type.scope, code)
2985 def generate_execution_code(self, code):
2986 # This is needed to generate evaluation code for
2987 # default values of method arguments.
2988 if self.body:
2989 self.body.generate_execution_code(code)
2991 def annotate(self, code):
2992 if self.body:
2993 self.body.annotate(code)
2996 class PropertyNode(StatNode):
2997 # Definition of a property in an extension type.
2998 #
2999 # name string
3000 # doc EncodedString or None Doc string
3001 # body StatListNode
3003 child_attrs = ["body"]
3005 def analyse_declarations(self, env):
3006 entry = env.declare_property(self.name, self.doc, self.pos)
3007 if entry:
3008 entry.scope.directives = env.directives
3009 self.body.analyse_declarations(entry.scope)
3011 def analyse_expressions(self, env):
3012 self.body.analyse_expressions(env)
3014 def generate_function_definitions(self, env, code):
3015 self.body.generate_function_definitions(env, code)
3017 def generate_execution_code(self, code):
3018 pass
3020 def annotate(self, code):
3021 self.body.annotate(code)
3024 class GlobalNode(StatNode):
3025 # Global variable declaration.
3026 #
3027 # names [string]
3029 child_attrs = []
3031 def analyse_declarations(self, env):
3032 for name in self.names:
3033 env.declare_global(name, self.pos)
3035 def analyse_expressions(self, env):
3036 pass
3038 def generate_execution_code(self, code):
3039 pass
3042 class ExprStatNode(StatNode):
3043 # Expression used as a statement.
3044 #
3045 # expr ExprNode
3047 child_attrs = ["expr"]
3049 def analyse_declarations(self, env):
3050 import ExprNodes
3051 if isinstance(self.expr, ExprNodes.GeneralCallNode):
3052 func = self.expr.function.as_cython_attribute()
3053 if func == u'declare':
3054 args, kwds = self.expr.explicit_args_kwds()
3055 if len(args):
3056 error(self.expr.pos, "Variable names must be specified.")
3057 for var, type_node in kwds.key_value_pairs:
3058 type = type_node.analyse_as_type(env)
3059 if type is None:
3060 error(type_node.pos, "Unknown type")
3061 else:
3062 env.declare_var(var.value, type, var.pos, is_cdef = True)
3063 self.__class__ = PassStatNode
3065 def analyse_expressions(self, env):
3066 self.expr.analyse_expressions(env)
3068 def generate_execution_code(self, code):
3069 self.expr.generate_evaluation_code(code)
3070 if not self.expr.is_temp and self.expr.result():
3071 code.putln("%s;" % self.expr.result())
3072 self.expr.generate_disposal_code(code)
3073 self.expr.free_temps(code)
3075 def annotate(self, code):
3076 self.expr.annotate(code)
3079 class AssignmentNode(StatNode):
3080 # Abstract base class for assignment nodes.
3081 #
3082 # The analyse_expressions and generate_execution_code
3083 # phases of assignments are split into two sub-phases
3084 # each, to enable all the right hand sides of a
3085 # parallel assignment to be evaluated before assigning
3086 # to any of the left hand sides.
3088 def analyse_expressions(self, env):
3089 self.analyse_types(env)
3091 # def analyse_expressions(self, env):
3092 # self.analyse_expressions_1(env)
3093 # self.analyse_expressions_2(env)
3095 def generate_execution_code(self, code):
3096 self.generate_rhs_evaluation_code(code)
3097 self.generate_assignment_code(code)
3100 class SingleAssignmentNode(AssignmentNode):
3101 # The simplest case:
3102 #
3103 # a = b
3104 #
3105 # lhs ExprNode Left hand side
3106 # rhs ExprNode Right hand side
3107 # first bool Is this guaranteed the first assignment to lhs?
3109 child_attrs = ["lhs", "rhs"]
3110 first = False
3111 declaration_only = False
3113 def analyse_declarations(self, env):
3114 import ExprNodes
3116 # handle declarations of the form x = cython.foo()
3117 if isinstance(self.rhs, ExprNodes.CallNode):
3118 func_name = self.rhs.function.as_cython_attribute()
3119 if func_name:
3120 args, kwds = self.rhs.explicit_args_kwds()
3122 if func_name in ['declare', 'typedef']:
3123 if len(args) > 2 or kwds is not None:
3124 error(rhs.pos, "Can only declare one type at a time.")
3125 return
3126 type = args[0].analyse_as_type(env)
3127 if type is None:
3128 error(args[0].pos, "Unknown type")
3129 return
3130 lhs = self.lhs
3131 if func_name == 'declare':
3132 if isinstance(lhs, ExprNodes.NameNode):
3133 vars = [(lhs.name, lhs.pos)]
3134 elif isinstance(lhs, ExprNodes.TupleNode):
3135 vars = [(var.name, var.pos) for var in lhs.args]
3136 else:
3137 error(lhs.pos, "Invalid declaration")
3138 return
3139 for var, pos in vars:
3140 env.declare_var(var, type, pos, is_cdef = True)
3141 if len(args) == 2:
3142 # we have a value
3143 self.rhs = args[1]
3144 else:
3145 self.declaration_only = True
3146 else:
3147 self.declaration_only = True
3148 if not isinstance(lhs, ExprNodes.NameNode):
3149 error(lhs.pos, "Invalid declaration.")
3150 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3152 elif func_name in ['struct', 'union']:
3153 self.declaration_only = True
3154 if len(args) > 0 or kwds is None:
3155 error(rhs.pos, "Struct or union members must be given by name.")
3156 return
3157 members = []
3158 for member, type_node in kwds.key_value_pairs:
3159 type = type_node.analyse_as_type(env)
3160 if type is None:
3161 error(type_node.pos, "Unknown type")
3162 else:
3163 members.append((member.value, type, member.pos))
3164 if len(members) < len(kwds.key_value_pairs):
3165 return
3166 if not isinstance(self.lhs, ExprNodes.NameNode):
3167 error(self.lhs.pos, "Invalid declaration.")
3168 name = self.lhs.name
3169 scope = StructOrUnionScope(name)
3170 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3171 for member, type, pos in members:
3172 scope.declare_var(member, type, pos)
3174 if self.declaration_only:
3175 return
3176 else:
3177 self.lhs.analyse_target_declaration(env)
3179 def analyse_types(self, env, use_temp = 0):
3180 self.rhs.analyse_types(env)
3181 self.lhs.analyse_target_types(env)
3182 self.lhs.gil_assignment_check(env)
3183 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3184 if use_temp:
3185 self.rhs = self.rhs.coerce_to_temp(env)
3187 def generate_rhs_evaluation_code(self, code):
3188 self.rhs.generate_evaluation_code(code)
3190 def generate_assignment_code(self, code):
3191 self.lhs.generate_assignment_code(self.rhs, code)
3193 def annotate(self, code):
3194 self.lhs.annotate(code)
3195 self.rhs.annotate(code)
3198 class CascadedAssignmentNode(AssignmentNode):
3199 # An assignment with multiple left hand sides:
3200 #
3201 # a = b = c
3202 #
3203 # lhs_list [ExprNode] Left hand sides
3204 # rhs ExprNode Right hand sides
3205 #
3206 # Used internally:
3207 #
3208 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3210 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3211 coerced_rhs_list = None
3213 def analyse_declarations(self, env):
3214 for lhs in self.lhs_list:
3215 lhs.analyse_target_declaration(env)
3217 def analyse_types(self, env, use_temp = 0):
3218 self.rhs.analyse_types(env)
3219 if not self.rhs.is_simple():
3220 if use_temp:
3221 self.rhs = self.rhs.coerce_to_temp(env)
3222 else:
3223 self.rhs = self.rhs.coerce_to_simple(env)
3224 from ExprNodes import CloneNode
3225 self.coerced_rhs_list = []
3226 for lhs in self.lhs_list:
3227 lhs.analyse_target_types(env)
3228 lhs.gil_assignment_check(env)
3229 rhs = CloneNode(self.rhs)
3230 rhs = rhs.coerce_to(lhs.type, env)
3231 self.coerced_rhs_list.append(rhs)
3233 def generate_rhs_evaluation_code(self, code):
3234 self.rhs.generate_evaluation_code(code)
3236 def generate_assignment_code(self, code):
3237 for i in range(len(self.lhs_list)):
3238 lhs = self.lhs_list[i]
3239 rhs = self.coerced_rhs_list[i]
3240 rhs.generate_evaluation_code(code)
3241 lhs.generate_assignment_code(rhs, code)
3242 # Assignment has disposed of the cloned RHS
3243 self.rhs.generate_disposal_code(code)
3244 self.rhs.free_temps(code)
3246 def annotate(self, code):
3247 for i in range(len(self.lhs_list)):
3248 lhs = self.lhs_list[i].annotate(code)
3249 rhs = self.coerced_rhs_list[i].annotate(code)
3250 self.rhs.annotate(code)
3253 class ParallelAssignmentNode(AssignmentNode):
3254 # A combined packing/unpacking assignment:
3255 #
3256 # a, b, c = d, e, f
3257 #
3258 # This has been rearranged by the parser into
3259 #
3260 # a = d ; b = e ; c = f
3261 #
3262 # but we must evaluate all the right hand sides
3263 # before assigning to any of the left hand sides.
3264 #
3265 # stats [AssignmentNode] The constituent assignments
3267 child_attrs = ["stats"]
3269 def analyse_declarations(self, env):
3270 for stat in self.stats:
3271 stat.analyse_declarations(env)
3273 def analyse_expressions(self, env):
3274 for stat in self.stats:
3275 stat.analyse_types(env, use_temp = 1)
3277 # def analyse_expressions(self, env):
3278 # for stat in self.stats:
3279 # stat.analyse_expressions_1(env, use_temp = 1)
3280 # for stat in self.stats:
3281 # stat.analyse_expressions_2(env)
3283 def generate_execution_code(self, code):
3284 for stat in self.stats:
3285 stat.generate_rhs_evaluation_code(code)
3286 for stat in self.stats:
3287 stat.generate_assignment_code(code)
3289 def annotate(self, code):
3290 for stat in self.stats:
3291 stat.annotate(code)
3294 class InPlaceAssignmentNode(AssignmentNode):
3295 # An in place arithmatic operand:
3296 #
3297 # a += b
3298 # a -= b
3299 # ...
3300 #
3301 # lhs ExprNode Left hand side
3302 # rhs ExprNode Right hand side
3303 # op char one of "+-*/%^&|"
3304 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3305 #
3306 # This code is a bit tricky because in order to obey Python
3307 # semantics the sub-expressions (e.g. indices) of the lhs must
3308 # not be evaluated twice. So we must re-use the values calculated
3309 # in evaluation phase for the assignment phase as well.
3310 # Fortunately, the type of the lhs node is fairly constrained
3311 # (it must be a NameNode, AttributeNode, or IndexNode).
3313 child_attrs = ["lhs", "rhs"]
3314 dup = None
3316 def analyse_declarations(self, env):
3317 self.lhs.analyse_target_declaration(env)
3319 def analyse_types(self, env):
3320 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3321 self.rhs.analyse_types(env)
3322 self.lhs.analyse_target_types(env)
3323 import ExprNodes
3324 if self.lhs.type.is_pyobject:
3325 self.rhs = self.rhs.coerce_to_pyobject(env)
3326 elif self.rhs.type.is_pyobject:
3327 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3328 if self.lhs.type.is_pyobject:
3329 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3330 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3332 def generate_execution_code(self, code):
3333 import ExprNodes
3334 self.rhs.generate_evaluation_code(code)
3335 self.dup.generate_subexpr_evaluation_code(code)
3336 if self.dup.is_temp:
3337 self.dup.allocate_temp_result(code)
3338 # self.dup.generate_result_code is run only if it is not buffer access
3339 if self.operator == "**":
3340 extra = ", Py_None"
3341 else:
3342 extra = ""
3343 if self.lhs.type.is_pyobject:
3344 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3345 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3346 self.dup.generate_result_code(code)
3347 self.result_value_temp.allocate(code)
3348 code.putln(
3349 "%s = %s(%s, %s%s); %s" % (
3350 self.result_value.result(),
3351 self.py_operation_function(),
3352 self.dup.py_result(),
3353 self.rhs.py_result(),
3354 extra,
3355 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3356 code.put_gotref(self.result_value.py_result())
3357 self.result_value.generate_evaluation_code(code) # May be a type check...
3358 self.rhs.generate_disposal_code(code)
3359 self.rhs.free_temps(code)
3360 self.dup.generate_disposal_code(code)
3361 self.dup.free_temps(code)
3362 self.lhs.generate_assignment_code(self.result_value, code)
3363 self.result_value_temp.release(code)
3364 else:
3365 c_op = self.operator
3366 if c_op == "//":
3367 c_op = "/"
3368 elif c_op == "**":
3369 error(self.pos, "No C inplace power operator")
3370 elif self.lhs.type.is_complex:
3371 error(self.pos, "Inplace operators not implemented for complex types.")
3373 # have to do assignment directly to avoid side-effects
3374 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3375 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3376 else:
3377 self.dup.generate_result_code(code)
3378 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3379 self.rhs.generate_disposal_code(code)
3380 self.rhs.free_temps(code)
3381 if self.dup.is_temp:
3382 self.dup.generate_subexpr_disposal_code(code)
3383 self.dup.free_subexpr_temps(code)
3385 def create_dup_node(self, env):
3386 import ExprNodes
3387 self.dup = self.lhs
3388 self.dup.analyse_types(env)
3389 if isinstance(self.lhs, ExprNodes.NameNode):
3390 target_lhs = ExprNodes.NameNode(self.dup.pos,
3391 name = self.dup.name,
3392 is_temp = self.dup.is_temp,
3393 entry = self.dup.entry)
3394 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3395 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3396 obj = ExprNodes.CloneNode(self.lhs.obj),
3397 attribute = self.dup.attribute,
3398 is_temp = self.dup.is_temp)
3399 elif isinstance(self.lhs, ExprNodes.IndexNode):
3400 if self.lhs.index:
3401 index = ExprNodes.CloneNode(self.lhs.index)
3402 else:
3403 index = None
3404 if self.lhs.indices:
3405 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3406 else:
3407 indices = []
3408 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3409 base = ExprNodes.CloneNode(self.dup.base),
3410 index = index,
3411 indices = indices,
3412 is_temp = self.dup.is_temp)
3413 else:
3414 assert False
3415 self.lhs = target_lhs
3416 return self.dup
3418 def py_operation_function(self):
3419 return self.py_functions[self.operator]
3421 py_functions = {
3422 "|": "PyNumber_InPlaceOr",
3423 "^": "PyNumber_InPlaceXor",
3424 "&": "PyNumber_InPlaceAnd",
3425 "+": "PyNumber_InPlaceAdd",
3426 "-": "PyNumber_InPlaceSubtract",
3427 "*": "PyNumber_InPlaceMultiply",
3428 "/": "__Pyx_PyNumber_InPlaceDivide",
3429 "%": "PyNumber_InPlaceRemainder",
3430 "<<": "PyNumber_InPlaceLshift",
3431 ">>": "PyNumber_InPlaceRshift",
3432 "**": "PyNumber_InPlacePower",
3433 "//": "PyNumber_InPlaceFloorDivide",
3434 }
3436 def annotate(self, code):
3437 self.lhs.annotate(code)
3438 self.rhs.annotate(code)
3439 self.dup.annotate(code)
3441 def create_binop_node(self):
3442 import ExprNodes
3443 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3446 class PrintStatNode(StatNode):
3447 # print statement
3448 #
3449 # arg_tuple TupleNode
3450 # stream ExprNode or None (stdout)
3451 # append_newline boolean
3453 child_attrs = ["arg_tuple", "stream"]
3455 def analyse_expressions(self, env):
3456 if self.stream:
3457 self.stream.analyse_expressions(env)
3458 self.stream = self.stream.coerce_to_pyobject(env)
3459 self.arg_tuple.analyse_expressions(env)
3460 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3461 env.use_utility_code(printing_utility_code)
3462 if len(self.arg_tuple.args) == 1 and self.append_newline:
3463 env.use_utility_code(printing_one_utility_code)
3465 nogil_check = Node.gil_error
3466 gil_message = "Python print statement"
3468 def generate_execution_code(self, code):
3469 if self.stream:
3470 self.stream.generate_evaluation_code(code)
3471 stream_result = self.stream.py_result()
3472 else:
3473 stream_result = '0'
3474 if len(self.arg_tuple.args) == 1 and self.append_newline:
3475 arg = self.arg_tuple.args[0]
3476 arg.generate_evaluation_code(code)
3478 code.putln(
3479 "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
3480 stream_result,
3481 arg.py_result(),
3482 code.error_goto(self.pos)))
3483 arg.generate_disposal_code(code)
3484 arg.free_temps(code)
3485 else:
3486 self.arg_tuple.generate_evaluation_code(code)
3487 code.putln(
3488 "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
3489 stream_result,
3490 self.arg_tuple.py_result(),
3491 self.append_newline,
3492 code.error_goto(self.pos)))
3493 self.arg_tuple.generate_disposal_code(code)
3494 self.arg_tuple.free_temps(code)
3496 if self.stream:
3497 self.stream.generate_disposal_code(code)
3498 self.stream.free_temps(code)
3500 def annotate(self, code):
3501 if self.stream:
3502 self.stream.annotate(code)
3503 self.arg_tuple.annotate(code)
3506 class ExecStatNode(StatNode):
3507 # exec statement
3508 #
3509 # args [ExprNode]
3511 child_attrs = ["args"]
3513 def analyse_expressions(self, env):
3514 for i, arg in enumerate(self.args):
3515 arg.analyse_expressions(env)
3516 arg = arg.coerce_to_pyobject(env)
3517 self.args[i] = arg
3518 env.use_utility_code(Builtin.pyexec_utility_code)
3520 nogil_check = Node.gil_error
3521 gil_message = "Python exec statement"
3523 def generate_execution_code(self, code):
3524 args = []
3525 for arg in self.args:
3526 arg.generate_evaluation_code(code)
3527 args.append( arg.py_result() )
3528 args = tuple(args + ['0', '0'][:3-len(args)])
3529 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3530 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3531 (temp_result,) + args))
3532 for arg in self.args:
3533 arg.generate_disposal_code(code)
3534 arg.free_temps(code)
3535 code.putln(
3536 code.error_goto_if_null(temp_result, self.pos))
3537 code.put_gotref(temp_result)
3538 code.put_decref_clear(temp_result, py_object_type)
3539 code.funcstate.release_temp(temp_result)
3541 def annotate(self, code):
3542 for arg in self.args:
3543 arg.annotate(code)
3546 class DelStatNode(StatNode):
3547 # del statement
3548 #
3549 # args [ExprNode]
3551 child_attrs = ["args"]
3553 def analyse_declarations(self, env):
3554 for arg in self.args:
3555 arg.analyse_target_declaration(env)
3557 def analyse_expressions(self, env):
3558 for arg in self.args:
3559 arg.analyse_target_expression(env, None)
3560 if arg.type.is_pyobject:
3561 pass
3562 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3563 self.cpp_check(env)
3564 elif arg.type.is_cpp_class:
3565 error(arg.pos, "Deletion of non-heap C++ object")
3566 else:
3567 error(arg.pos, "Deletion of non-Python, non-C++ object")
3568 #arg.release_target_temp(env)
3570 def nogil_check(self, env):
3571 for arg in self.args:
3572 if arg.type.is_pyobject:
3573 self.gil_error()
3575 gil_message = "Deleting Python object"
3577 def generate_execution_code(self, code):
3578 for arg in self.args:
3579 if arg.type.is_pyobject:
3580 arg.generate_deletion_code(code)
3581 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3582 arg.generate_result_code(code)
3583 code.putln("delete %s;" % arg.result())
3584 # else error reported earlier
3586 def annotate(self, code):
3587 for arg in self.args:
3588 arg.annotate(code)
3591 class PassStatNode(StatNode):
3592 # pass statement
3594 child_attrs = []
3596 def analyse_expressions(self, env):
3597 pass
3599 def generate_execution_code(self, code):
3600 pass
3603 class BreakStatNode(StatNode):
3605 child_attrs = []
3607 def analyse_expressions(self, env):
3608 pass
3610 def generate_execution_code(self, code):
3611 if not code.break_label:
3612 error(self.pos, "break statement not inside loop")
3613 else:
3614 code.put_goto(code.break_label)
3617 class ContinueStatNode(StatNode):
3619 child_attrs = []
3621 def analyse_expressions(self, env):
3622 pass
3624 def generate_execution_code(self, code):
3625 if code.funcstate.in_try_finally:
3626 error(self.pos, "continue statement inside try of try...finally")
3627 elif not code.continue_label:
3628 error(self.pos, "continue statement not inside loop")
3629 else:
3630 code.put_goto(code.continue_label)
3633 class ReturnStatNode(StatNode):
3634 # return statement
3635 #
3636 # value ExprNode or None
3637 # return_type PyrexType
3639 child_attrs = ["value"]
3641 def analyse_expressions(self, env):
3642 return_type = env.return_type
3643 self.return_type = return_type
3644 if not return_type:
3645 error(self.pos, "Return not inside a function body")
3646 return
3647 if self.value:
3648 self.value.analyse_types(env)
3649 if return_type.is_void or return_type.is_returncode:
3650 error(self.value.pos,
3651 "Return with value in void function")
3652 else:
3653 self.value = self.value.coerce_to(env.return_type, env)
3654 else:
3655 if (not return_type.is_void
3656 and not return_type.is_pyobject
3657 and not return_type.is_returncode):
3658 error(self.pos, "Return value required")
3660 def nogil_check(self, env):
3661 if self.return_type.is_pyobject:
3662 self.gil_error()
3664 gil_message = "Returning Python object"
3666 def generate_execution_code(self, code):
3667 code.mark_pos(self.pos)
3668 if not self.return_type:
3669 # error reported earlier
3670 return
3671 if self.return_type.is_pyobject:
3672 code.put_xdecref(Naming.retval_cname,
3673 self.return_type)
3674 if self.value:
3675 self.value.generate_evaluation_code(code)
3676 self.value.make_owned_reference(code)
3677 code.putln(
3678 "%s = %s;" % (
3679 Naming.retval_cname,
3680 self.value.result_as(self.return_type)))
3681 self.value.generate_post_assignment_code(code)
3682 self.value.free_temps(code)
3683 else:
3684 if self.return_type.is_pyobject:
3685 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3686 elif self.return_type.is_returncode:
3687 code.putln(
3688 "%s = %s;" % (
3689 Naming.retval_cname,
3690 self.return_type.default_value))
3691 for cname, type in code.funcstate.temps_holding_reference():
3692 code.put_decref_clear(cname, type)
3693 code.put_goto(code.return_label)
3695 def annotate(self, code):
3696 if self.value:
3697 self.value.annotate(code)
3700 class RaiseStatNode(StatNode):
3701 # raise statement
3702 #
3703 # exc_type ExprNode or None
3704 # exc_value ExprNode or None
3705 # exc_tb ExprNode or None
3707 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3709 def analyse_expressions(self, env):
3710 if self.exc_type:
3711 self.exc_type.analyse_types(env)
3712 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3713 if self.exc_value:
3714 self.exc_value.analyse_types(env)
3715 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3716 if self.exc_tb:
3717 self.exc_tb.analyse_types(env)
3718 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3719 env.use_utility_code(raise_utility_code)
3721 nogil_check = Node.gil_error
3722 gil_message = "Raising exception"
3724 def generate_execution_code(self, code):
3725 if self.exc_type:
3726 self.exc_type.generate_evaluation_code(code)
3727 type_code = self.exc_type.py_result()
3728 else:
3729 type_code = "0"
3730 if self.exc_value:
3731 self.exc_value.generate_evaluation_code(code)
3732 value_code = self.exc_value.py_result()
3733 else:
3734 value_code = "0"
3735 if self.exc_tb:
3736 self.exc_tb.generate_evaluation_code(code)
3737 tb_code = self.exc_tb.py_result()
3738 else:
3739 tb_code = "0"
3740 code.putln(
3741 "__Pyx_Raise(%s, %s, %s);" % (
3742 type_code,
3743 value_code,
3744 tb_code))
3745 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3746 if obj:
3747 obj.generate_disposal_code(code)
3748 obj.free_temps(code)
3749 code.putln(
3750 code.error_goto(self.pos))
3752 def annotate(self, code):
3753 if self.exc_type:
3754 self.exc_type.annotate(code)
3755 if self.exc_value:
3756 self.exc_value.annotate(code)
3757 if self.exc_tb:
3758 self.exc_tb.annotate(code)
3761 class ReraiseStatNode(StatNode):
3763 child_attrs = []
3765 def analyse_expressions(self, env):
3766 env.use_utility_code(restore_exception_utility_code)
3768 nogil_check = Node.gil_error
3769 gil_message = "Raising exception"
3771 def generate_execution_code(self, code):
3772 vars = code.funcstate.exc_vars
3773 if vars:
3774 for varname in vars:
3775 code.put_giveref(varname)
3776 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3777 for varname in vars:
3778 code.put("%s = 0; " % varname)
3779 code.putln()
3780 code.putln(code.error_goto(self.pos))
3781 else:
3782 error(self.pos, "Reraise not inside except clause")
3785 class AssertStatNode(StatNode):
3786 # assert statement
3787 #
3788 # cond ExprNode
3789 # value ExprNode or None
3791 child_attrs = ["cond", "value"]
3793 def analyse_expressions(self, env):
3794 self.cond = self.cond.analyse_boolean_expression(env)
3795 if self.value:
3796 self.value.analyse_types(env)
3797 self.value = self.value.coerce_to_pyobject(env)
3799 nogil_check = Node.gil_error
3800 gil_message = "Raising exception"
3802 def generate_execution_code(self, code):
3803 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3804 self.cond.generate_evaluation_code(code)
3805 code.putln(
3806 "if (unlikely(!%s)) {" %
3807 self.cond.result())
3808 if self.value:
3809 self.value.generate_evaluation_code(code)
3810 code.putln(
3811 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3812 self.value.py_result())
3813 self.value.generate_disposal_code(code)
3814 self.value.free_temps(code)
3815 else:
3816 code.putln(
3817 "PyErr_SetNone(PyExc_AssertionError);")
3818 code.putln(
3819 code.error_goto(self.pos))
3820 code.putln(
3821 "}")
3822 self.cond.generate_disposal_code(code)
3823 self.cond.free_temps(code)
3824 code.putln("#endif")
3826 def annotate(self, code):
3827 self.cond.annotate(code)
3828 if self.value:
3829 self.value.annotate(code)
3832 class IfStatNode(StatNode):
3833 # if statement
3834 #
3835 # if_clauses [IfClauseNode]
3836 # else_clause StatNode or None
3838 child_attrs = ["if_clauses", "else_clause"]
3840 def analyse_control_flow(self, env):
3841 env.start_branching(self.pos)
3842 for if_clause in self.if_clauses:
3843 if_clause.analyse_control_flow(env)
3844 env.next_branch(if_clause.end_pos())
3845 if self.else_clause:
3846 self.else_clause.analyse_control_flow(env)
3847 env.finish_branching(self.end_pos())
3849 def analyse_declarations(self, env):
3850 for if_clause in self.if_clauses:
3851 if_clause.analyse_declarations(env)
3852 if self.else_clause:
3853 self.else_clause.analyse_declarations(env)
3855 def analyse_expressions(self, env):
3856 for if_clause in self.if_clauses:
3857 if_clause.analyse_expressions(env)
3858 if self.else_clause:
3859 self.else_clause.analyse_expressions(env)
3861 def generate_execution_code(self, code):
3862 code.mark_pos(self.pos)
3863 end_label = code.new_label()
3864 for if_clause in self.if_clauses:
3865 if_clause.generate_execution_code(code, end_label)
3866 if self.else_clause:
3867 code.putln("/*else*/ {")
3868 self.else_clause.generate_execution_code(code)
3869 code.putln("}")
3870 code.put_label(end_label)
3872 def annotate(self, code):
3873 for if_clause in self.if_clauses:
3874 if_clause.annotate(code)
3875 if self.else_clause:
3876 self.else_clause.annotate(code)
3879 class IfClauseNode(Node):
3880 # if or elif clause in an if statement
3881 #
3882 # condition ExprNode
3883 # body StatNode
3885 child_attrs = ["condition", "body"]
3887 def analyse_control_flow(self, env):
3888 self.body.analyse_control_flow(env)
3890 def analyse_declarations(self, env):
3891 self.condition.analyse_declarations(env)
3892 self.body.analyse_declarations(env)
3894 def analyse_expressions(self, env):
3895 self.condition = \
3896 self.condition.analyse_temp_boolean_expression(env)
3897 self.body.analyse_expressions(env)
3899 def generate_execution_code(self, code, end_label):
3900 self.condition.generate_evaluation_code(code)
3901 code.putln(
3902 "if (%s) {" %
3903 self.condition.result())
3904 self.condition.generate_disposal_code(code)
3905 self.condition.free_temps(code)
3906 self.body.generate_execution_code(code)
3907 code.put_goto(end_label)
3908 code.putln("}")
3910 def annotate(self, code):
3911 self.condition.annotate(code)
3912 self.body.annotate(code)
3915 class SwitchCaseNode(StatNode):
3916 # Generated in the optimization of an if-elif-else node
3917 #
3918 # conditions [ExprNode]
3919 # body StatNode
3921 child_attrs = ['conditions', 'body']
3923 def generate_execution_code(self, code):
3924 for cond in self.conditions:
3925 code.mark_pos(cond.pos)
3926 cond.generate_evaluation_code(code)
3927 code.putln("case %s:" % cond.result())
3928 self.body.generate_execution_code(code)
3929 code.putln("break;")
3931 def annotate(self, code):
3932 for cond in self.conditions:
3933 cond.annotate(code)
3934 self.body.annotate(code)
3936 class SwitchStatNode(StatNode):
3937 # Generated in the optimization of an if-elif-else node
3938 #
3939 # test ExprNode
3940 # cases [SwitchCaseNode]
3941 # else_clause StatNode or None
3943 child_attrs = ['test', 'cases', 'else_clause']
3945 def generate_execution_code(self, code):
3946 code.putln("switch (%s) {" % self.test.result())
3947 for case in self.cases:
3948 case.generate_execution_code(code)
3949 if self.else_clause is not None:
3950 code.putln("default:")
3951 self.else_clause.generate_execution_code(code)
3952 code.putln("break;")
3953 code.putln("}")
3955 def annotate(self, code):
3956 self.test.annotate(code)
3957 for case in self.cases:
3958 case.annotate(code)
3959 if self.else_clause is not None:
3960 self.else_clause.annotate(code)
3962 class LoopNode(object):
3964 def analyse_control_flow(self, env):
3965 env.start_branching(self.pos)
3966 self.body.analyse_control_flow(env)
3967 env.next_branch(self.body.end_pos())
3968 if self.else_clause:
3969 self.else_clause.analyse_control_flow(env)
3970 env.finish_branching(self.end_pos())
3973 class WhileStatNode(LoopNode, StatNode):
3974 # while statement
3975 #
3976 # condition ExprNode
3977 # body StatNode
3978 # else_clause StatNode
3980 child_attrs = ["condition", "body", "else_clause"]
3982 def analyse_declarations(self, env):
3983 self.body.analyse_declarations(env)
3984 if self.else_clause:
3985 self.else_clause.analyse_declarations(env)
3987 def analyse_expressions(self, env):
3988 self.condition = \
3989 self.condition.analyse_temp_boolean_expression(env)
3990 self.body.analyse_expressions(env)
3991 if self.else_clause:
3992 self.else_clause.analyse_expressions(env)
3994 def generate_execution_code(self, code):
3995 old_loop_labels = code.new_loop_labels()
3996 code.putln(
3997 "while (1) {")
3998 self.condition.generate_evaluation_code(code)
3999 self.condition.generate_disposal_code(code)
4000 code.putln(
4001 "if (!%s) break;" %
4002 self.condition.result())
4003 self.condition.free_temps(code)
4004 self.body.generate_execution_code(code)
4005 code.put_label(code.continue_label)
4006 code.putln("}")
4007 break_label = code.break_label
4008 code.set_loop_labels(old_loop_labels)
4009 if self.else_clause:
4010 code.putln("/*else*/ {")
4011 self.else_clause.generate_execution_code(code)
4012 code.putln("}")
4013 code.put_label(break_label)
4015 def annotate(self, code):
4016 self.condition.annotate(code)
4017 self.body.annotate(code)
4018 if self.else_clause:
4019 self.else_clause.annotate(code)
4022 def ForStatNode(pos, **kw):
4023 if 'iterator' in kw:
4024 return ForInStatNode(pos, **kw)
4025 else:
4026 return ForFromStatNode(pos, **kw)
4028 class ForInStatNode(LoopNode, StatNode):
4029 # for statement
4030 #
4031 # target ExprNode
4032 # iterator IteratorNode
4033 # body StatNode
4034 # else_clause StatNode
4035 # item NextNode used internally
4037 child_attrs = ["target", "iterator", "body", "else_clause"]
4038 item = None
4040 def analyse_declarations(self, env):
4041 self.target.analyse_target_declaration(env)
4042 self.body.analyse_declarations(env)
4043 if self.else_clause:
4044 self.else_clause.analyse_declarations(env)
4046 def analyse_expressions(self, env):
4047 import ExprNodes
4048 self.target.analyse_target_types(env)
4049 self.iterator.analyse_expressions(env)
4050 self.item = ExprNodes.NextNode(self.iterator, env)
4051 self.item = self.item.coerce_to(self.target.type, env)
4052 self.body.analyse_expressions(env)
4053 if self.else_clause:
4054 self.else_clause.analyse_expressions(env)
4056 def generate_execution_code(self, code):
4057 old_loop_labels = code.new_loop_labels()
4058 self.iterator.allocate_counter_temp(code)
4059 self.iterator.generate_evaluation_code(code)
4060 code.putln(
4061 "for (;;) {")
4062 self.item.generate_evaluation_code(code)
4063 self.target.generate_assignment_code(self.item, code)
4064 self.body.generate_execution_code(code)
4065 code.put_label(code.continue_label)
4066 code.putln(
4067 "}")
4068 break_label = code.break_label
4069 code.set_loop_labels(old_loop_labels)
4070 if self.else_clause:
4071 code.putln("/*else*/ {")
4072 self.else_clause.generate_execution_code(code)
4073 code.putln("}")
4074 code.put_label(break_label)
4075 self.iterator.release_counter_temp(code)
4076 self.iterator.generate_disposal_code(code)
4077 self.iterator.free_temps(code)
4079 def annotate(self, code):
4080 self.target.annotate(code)
4081 self.iterator.annotate(code)
4082 self.body.annotate(code)
4083 if self.else_clause:
4084 self.else_clause.annotate(code)
4085 self.item.annotate(code)
4088 class ForFromStatNode(LoopNode, StatNode):
4089 # for name from expr rel name rel expr
4090 #
4091 # target NameNode
4092 # bound1 ExprNode
4093 # relation1 string
4094 # relation2 string
4095 # bound2 ExprNode
4096 # step ExprNode or None
4097 # body StatNode
4098 # else_clause StatNode or None
4099 #
4100 # Used internally:
4101 #
4102 # from_range bool
4103 # is_py_target bool
4104 # loopvar_node ExprNode (usually a NameNode or temp node)
4105 # py_loopvar_node PyTempNode or None
4106 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
4108 is_py_target = False
4109 loopvar_node = None
4110 py_loopvar_node = None
4111 from_range = False
4113 gil_message = "For-loop using object bounds or target"
4115 def nogil_check(self, env):
4116 for x in (self.target, self.bound1, self.bound2):
4117 if x.type.is_pyobject:
4118 self.gil_error()
4120 def analyse_declarations(self, env):
4121 self.target.analyse_target_declaration(env)
4122 self.body.analyse_declarations(env)
4123 if self.else_clause:
4124 self.else_clause.analyse_declarations(env)
4126 def analyse_expressions(self, env):
4127 import ExprNodes
4128 self.target.analyse_target_types(env)
4129 self.bound1.analyse_types(env)
4130 self.bound2.analyse_types(env)
4131 if self.step is not None:
4132 if isinstance(self.step, ExprNodes.UnaryMinusNode):
4133 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
4134 self.step.analyse_types(env)
4136 target_type = self.target.type
4137 if self.target.type.is_numeric:
4138 loop_type = self.target.type
4139 else:
4140 loop_type = PyrexTypes.c_int_type
4141 if not self.bound1.type.is_pyobject:
4142 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
4143 if not self.bound2.type.is_pyobject:
4144 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
4145 if self.step is not None and not self.step.type.is_pyobject:
4146 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
4147 self.bound1 = self.bound1.coerce_to(loop_type, env)
4148 self.bound2 = self.bound2.coerce_to(loop_type, env)
4149 if not self.bound2.is_literal:
4150 self.bound2 = self.bound2.coerce_to_temp(env)
4151 if self.step is not None:
4152 self.step = self.step.coerce_to(loop_type, env)
4153 if not self.step.is_literal:
4154 self.step = self.step.coerce_to_temp(env)
4156 target_type = self.target.type
4157 if not (target_type.is_pyobject or target_type.is_numeric):
4158 error(self.target.pos,
4159 "for-from loop variable must be c numeric type or Python object")
4160 if target_type.is_numeric:
4161 self.is_py_target = False
4162 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
4163 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
4164 self.loopvar_node = self.target
4165 self.py_loopvar_node = None
4166 else:
4167 self.is_py_target = True
4168 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
4169 self.loopvar_node = c_loopvar_node
4170 self.py_loopvar_node = \
4171 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
4172 self.body.analyse_expressions(env)
4173 if self.else_clause:
4174 self.else_clause.analyse_expressions(env)
4176 def generate_execution_code(self, code):
4177 old_loop_labels = code.new_loop_labels()
4178 from_range = self.from_range
4179 self.bound1.generate_evaluation_code(code)
4180 self.bound2.generate_evaluation_code(code)
4181 offset, incop = self.relation_table[self.relation1]
4182 if self.step is not None:
4183 self.step.generate_evaluation_code(code)
4184 step = self.step.result()
4185 incop = "%s=%s" % (incop[0], step)
4186 import ExprNodes
4187 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4188 self.loopvar_node.allocate(code)
4189 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4190 self.py_loopvar_node.allocate(code)
4191 if from_range:
4192 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4193 else:
4194 loopvar_name = self.loopvar_node.result()
4195 code.putln(
4196 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4197 loopvar_name,
4198 self.bound1.result(), offset,
4199 loopvar_name, self.relation2, self.bound2.result(),
4200 loopvar_name, incop))
4201 if self.py_loopvar_node:
4202 self.py_loopvar_node.generate_evaluation_code(code)
4203 self.target.generate_assignment_code(self.py_loopvar_node, code)
4204 elif from_range:
4205 code.putln("%s = %s;" % (
4206 self.target.result(), loopvar_name))
4207 self.body.generate_execution_code(code)
4208 code.put_label(code.continue_label)
4209 if self.py_loopvar_node:
4210 # This mess is to make for..from loops with python targets behave
4211 # exactly like those with C targets with regards to re-assignment
4212 # of the loop variable.
4213 import ExprNodes
4214 if self.target.entry.is_pyglobal:
4215 # We know target is a NameNode, this is the only ugly case.
4216 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4217 target_node.allocate(code)
4218 interned_cname = code.intern_identifier(self.target.entry.name)
4219 code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
4220 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4221 target_node.result(),
4222 Naming.module_cname,
4223 interned_cname,
4224 code.error_goto_if_null(target_node.result(), self.target.pos)))
4225 code.put_gotref(target_node.result())
4226 else:
4227 target_node = self.target
4228 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4229 from_py_node.temp_code = loopvar_name
4230 from_py_node.generate_result_code(code)
4231 if self.target.entry.is_pyglobal:
4232 code.put_decref(target_node.result(), target_node.type)
4233 target_node.release(code)
4234 code.putln("}")
4235 if self.py_loopvar_node:
4236 # This is potentially wasteful, but we don't want the semantics to
4237 # depend on whether or not the loop is a python type.
4238 self.py_loopvar_node.generate_evaluation_code(code)
4239 self.target.generate_assignment_code(self.py_loopvar_node, code)
4240 if from_range:
4241 code.funcstate.release_temp(loopvar_name)
4242 break_label = code.break_label
4243 code.set_loop_labels(old_loop_labels)
4244 if self.else_clause:
4245 code.putln("/*else*/ {")
4246 self.else_clause.generate_execution_code(code)
4247 code.putln("}")
4248 code.put_label(break_label)
4249 self.bound1.generate_disposal_code(code)
4250 self.bound1.free_temps(code)
4251 self.bound2.generate_disposal_code(code)
4252 self.bound2.free_temps(code)
4253 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4254 self.loopvar_node.release(code)
4255 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4256 self.py_loopvar_node.release(code)
4257 if self.step is not None:
4258 self.step.generate_disposal_code(code)
4259 self.step.free_temps(code)
4261 relation_table = {
4262 # {relop : (initial offset, increment op)}
4263 '<=': ("", "++"),
4264 '<' : ("+1", "++"),
4265 '>=': ("", "--"),
4266 '>' : ("-1", "--")
4267 }
4269 def annotate(self, code):
4270 self.target.annotate(code)
4271 self.bound1.annotate(code)
4272 self.bound2.annotate(code)
4273 if self.step:
4274 self.bound2.annotate(code)
4275 self.body.annotate(code)
4276 if self.else_clause:
4277 self.else_clause.annotate(code)
4280 class WithStatNode(StatNode):
4281 """
4282 Represents a Python with statement.
4284 This is only used at parse tree level; and is not present in
4285 analysis or generation phases.
4286 """
4287 # manager The with statement manager object
4288 # target Node (lhs expression)
4289 # body StatNode
4290 child_attrs = ["manager", "target", "body"]
4292 class TryExceptStatNode(StatNode):
4293 # try .. except statement
4294 #
4295 # body StatNode
4296 # except_clauses [ExceptClauseNode]
4297 # else_clause StatNode or None
4299 child_attrs = ["body", "except_clauses", "else_clause"]
4301 def analyse_control_flow(self, env):
4302 env.start_branching(self.pos)
4303 self.body.analyse_control_flow(env)
4304 successful_try = env.control_flow # grab this for later
4305 env.next_branch(self.body.end_pos())
4306 env.finish_branching(self.body.end_pos())
4308 env.start_branching(self.except_clauses[0].pos)
4309 for except_clause in self.except_clauses:
4310 except_clause.analyse_control_flow(env)
4311 env.next_branch(except_clause.end_pos())
4313 # the else cause it executed only when the try clause finishes
4314 env.control_flow.incoming = successful_try
4315 if self.else_clause:
4316 self.else_clause.analyse_control_flow(env)
4317 env.finish_branching(self.end_pos())
4319 def analyse_declarations(self, env):
4320 self.body.analyse_declarations(env)
4321 for except_clause in self.except_clauses:
4322 except_clause.analyse_declarations(env)
4323 if self.else_clause:
4324 self.else_clause.analyse_declarations(env)
4325 env.use_utility_code(reset_exception_utility_code)
4327 def analyse_expressions(self, env):
4328 self.body.analyse_expressions(env)
4329 default_clause_seen = 0
4330 for except_clause in self.except_clauses:
4331 except_clause.analyse_expressions(env)
4332 if default_clause_seen:
4333 error(except_clause.pos, "default 'except:' must be last")
4334 if not except_clause.pattern:
4335 default_clause_seen = 1
4336 self.has_default_clause = default_clause_seen
4337 if self.else_clause:
4338 self.else_clause.analyse_expressions(env)
4340 nogil_check = Node.gil_error
4341 gil_message = "Try-except statement"
4343 def generate_execution_code(self, code):
4344 old_return_label = code.return_label
4345 old_break_label = code.break_label
4346 old_continue_label = code.continue_label
4347 old_error_label = code.new_error_label()
4348 our_error_label = code.error_label
4349 except_end_label = code.new_label('exception_handled')
4350 except_error_label = code.new_label('except_error')
4351 except_return_label = code.new_label('except_return')
4352 try_return_label = code.new_label('try_return')
4353 try_break_label = code.new_label('try_break')
4354 try_continue_label = code.new_label('try_continue')
4355 try_end_label = code.new_label('try_end')
4357 code.putln("{")
4358 code.putln("PyObject %s;" %
4359 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4360 code.putln("__Pyx_ExceptionSave(%s);" %
4361 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4362 for var in Naming.exc_save_vars:
4363 code.put_xgotref(var)
4364 code.putln(
4365 "/*try:*/ {")
4366 code.return_label = try_return_label
4367 code.break_label = try_break_label
4368 code.continue_label = try_continue_label
4369 self.body.generate_execution_code(code)
4370 code.putln(
4371 "}")
4372 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4373 code.error_label = except_error_label
4374 code.return_label = except_return_label
4375 if self.else_clause:
4376 code.putln(
4377 "/*else:*/ {")
4378 self.else_clause.generate_execution_code(code)
4379 code.putln(
4380 "}")
4381 for var in Naming.exc_save_vars:
4382 code.put_xdecref_clear(var, py_object_type)
4383 code.put_goto(try_end_label)
4384 if code.label_used(try_return_label):
4385 code.put_label(try_return_label)
4386 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4387 code.putln("__Pyx_ExceptionReset(%s);" %
4388 ', '.join(Naming.exc_save_vars))
4389 code.put_goto(old_return_label)
4390 code.put_label(our_error_label)
4391 for temp_name, type in temps_to_clean_up:
4392 code.put_xdecref_clear(temp_name, type)
4393 for except_clause in self.except_clauses:
4394 except_clause.generate_handling_code(code, except_end_label)
4396 error_label_used = code.label_used(except_error_label)
4397 if error_label_used or not self.has_default_clause:
4398 if error_label_used:
4399 code.put_label(except_error_label)
4400 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4401 code.putln("__Pyx_ExceptionReset(%s);" %
4402 ', '.join(Naming.exc_save_vars))
4403 code.put_goto(old_error_label)
4405 for exit_label, old_label in zip(
4406 [try_break_label, try_continue_label, except_return_label],
4407 [old_break_label, old_continue_label, old_return_label]):
4409 if code.label_used(exit_label):
4410 code.put_label(exit_label)
4411 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4412 code.putln("__Pyx_ExceptionReset(%s);" %
4413 ', '.join(Naming.exc_save_vars))
4414 code.put_goto(old_label)
4416 if code.label_used(except_end_label):
4417 code.put_label(except_end_label)
4418 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4419 code.putln("__Pyx_ExceptionReset(%s);" %
4420 ', '.join(Naming.exc_save_vars))
4421 code.put_label(try_end_label)
4422 code.putln("}")
4424 code.return_label = old_return_label
4425 code.break_label = old_break_label
4426 code.continue_label = old_continue_label
4427 code.error_label = old_error_label
4429 def annotate(self, code):
4430 self.body.annotate(code)
4431 for except_node in self.except_clauses:
4432 except_node.annotate(code)
4433 if self.else_clause:
4434 self.else_clause.annotate(code)
4437 class ExceptClauseNode(Node):
4438 # Part of try ... except statement.
4439 #
4440 # pattern ExprNode
4441 # target ExprNode or None
4442 # body StatNode
4443 # excinfo_target NameNode or None optional target for exception info
4444 # match_flag string result of exception match
4445 # exc_value ExcValueNode used internally
4446 # function_name string qualified name of enclosing function
4447 # exc_vars (string * 3) local exception variables
4449 # excinfo_target is never set by the parser, but can be set by a transform
4450 # in order to extract more extensive information about the exception as a
4451 # sys.exc_info()-style tuple into a target variable
4453 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4455 exc_value = None
4456 excinfo_target = None
4458 def analyse_declarations(self, env):
4459 if self.target:
4460 self.target.analyse_target_declaration(env)
4461 if self.excinfo_target is not None:
4462 self.excinfo_target.analyse_target_declaration(env)
4463 self.body.analyse_declarations(env)
4465 def analyse_expressions(self, env):
4466 import ExprNodes
4467 genv = env.global_scope()
4468 self.function_name = env.qualified_name
4469 if self.pattern:
4470 self.pattern.analyse_expressions(env)
4471 self.pattern = self.pattern.coerce_to_pyobject(env)
4473 if self.target:
4474 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4475 self.target.analyse_target_expression(env, self.exc_value)
4476 if self.excinfo_target is not None:
4477 import ExprNodes
4478 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4479 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4480 self.excinfo_tuple.analyse_expressions(env)
4481 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4483 self.body.analyse_expressions(env)
4485 def generate_handling_code(self, code, end_label):
4486 code.mark_pos(self.pos)
4487 if self.pattern:
4488 self.pattern.generate_evaluation_code(code)
4490 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4491 code.putln(
4492 "%s = PyErr_ExceptionMatches(%s);" % (
4493 match_flag,
4494 self.pattern.py_result()))
4495 self.pattern.generate_disposal_code(code)
4496 self.pattern.free_temps(code)
4497 code.putln(
4498 "if (%s) {" %
4499 match_flag)
4500 code.funcstate.release_temp(match_flag)
4501 else:
4502 code.putln("/*except:*/ {")
4504 if not getattr(self.body, 'stats', True):
4505 # most simple case: no exception variable, empty body (pass)
4506 # => reset the exception state, done
4507 code.putln("PyErr_Restore(0,0,0);")
4508 code.put_goto(end_label)
4509 code.putln("}")
4510 return
4512 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4513 manage_ref=True)
4514 for i in xrange(3)]
4515 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4516 # We always have to fetch the exception value even if
4517 # there is no target, because this also normalises the
4518 # exception and stores it in the thread state.
4519 code.globalstate.use_utility_code(get_exception_utility_code)
4520 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4521 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4522 code.error_goto(self.pos)))
4523 for x in exc_vars:
4524 code.put_gotref(x)
4525 if self.target:
4526 self.exc_value.set_var(exc_vars[1])
4527 self.exc_value.generate_evaluation_code(code)
4528 self.target.generate_assignment_code(self.exc_value, code)
4529 if self.excinfo_target is not None:
4530 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4531 node.set_var(tempvar)
4532 self.excinfo_tuple.generate_evaluation_code(code)
4533 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4535 old_break_label, old_continue_label = code.break_label, code.continue_label
4536 code.break_label = code.new_label('except_break')
4537 code.continue_label = code.new_label('except_continue')
4539 old_exc_vars = code.funcstate.exc_vars
4540 code.funcstate.exc_vars = exc_vars
4541 self.body.generate_execution_code(code)
4542 code.funcstate.exc_vars = old_exc_vars
4543 for var in exc_vars:
4544 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4545 code.put_goto(end_label)
4547 if code.label_used(code.break_label):
4548 code.put_label(code.break_label)
4549 for var in exc_vars:
4550 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4551 code.put_goto(old_break_label)
4552 code.break_label = old_break_label
4554 if code.label_used(code.continue_label):
4555 code.put_label(code.continue_label)
4556 for var in exc_vars:
4557 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4558 code.put_goto(old_continue_label)
4559 code.continue_label = old_continue_label
4561 for temp in exc_vars:
4562 code.funcstate.release_temp(temp)
4564 code.putln(
4565 "}")
4567 def annotate(self, code):
4568 if self.pattern:
4569 self.pattern.annotate(code)
4570 if self.target:
4571 self.target.annotate(code)
4572 self.body.annotate(code)
4575 class TryFinallyStatNode(StatNode):
4576 # try ... finally statement
4577 #
4578 # body StatNode
4579 # finally_clause StatNode
4580 #
4581 # The plan is that we funnel all continue, break
4582 # return and error gotos into the beginning of the
4583 # finally block, setting a variable to remember which
4584 # one we're doing. At the end of the finally block, we
4585 # switch on the variable to figure out where to go.
4586 # In addition, if we're doing an error, we save the
4587 # exception on entry to the finally block and restore
4588 # it on exit.
4590 child_attrs = ["body", "finally_clause"]
4592 preserve_exception = 1
4594 disallow_continue_in_try_finally = 0
4595 # There doesn't seem to be any point in disallowing
4596 # continue in the try block, since we have no problem
4597 # handling it.
4599 def create_analysed(pos, env, body, finally_clause):
4600 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4601 return node
4602 create_analysed = staticmethod(create_analysed)
4604 def analyse_control_flow(self, env):
4605 env.start_branching(self.pos)
4606 self.body.analyse_control_flow(env)
4607 env.next_branch(self.body.end_pos())
4608 env.finish_branching(self.body.end_pos())
4609 self.finally_clause.analyse_control_flow(env)
4611 def analyse_declarations(self, env):
4612 self.body.analyse_declarations(env)
4613 self.finally_clause.analyse_declarations(env)
4615 def analyse_expressions(self, env):
4616 self.body.analyse_expressions(env)
4617 self.finally_clause.analyse_expressions(env)
4619 nogil_check = Node.gil_error
4620 gil_message = "Try-finally statement"
4622 def generate_execution_code(self, code):
4623 old_error_label = code.error_label
4624 old_labels = code.all_new_labels()
4625 new_labels = code.get_all_labels()
4626 new_error_label = code.error_label
4627 catch_label = code.new_label()
4628 code.putln(
4629 "/*try:*/ {")
4630 if self.disallow_continue_in_try_finally:
4631 was_in_try_finally = code.funcstate.in_try_finally
4632 code.funcstate.in_try_finally = 1
4633 self.body.generate_execution_code(code)
4634 if self.disallow_continue_in_try_finally:
4635 code.funcstate.in_try_finally = was_in_try_finally
4636 code.putln(
4637 "}")
4638 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4639 code.putln(
4640 "/*finally:*/ {")
4641 cases_used = []
4642 error_label_used = 0
4643 for i, new_label in enumerate(new_labels):
4644 if new_label in code.labels_used:
4645 cases_used.append(i)
4646 if new_label == new_error_label:
4647 error_label_used = 1
4648 error_label_case = i
4649 if cases_used:
4650 code.putln(
4651 "int __pyx_why;")
4652 if error_label_used and self.preserve_exception:
4653 code.putln(
4654 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4655 code.putln(
4656 "int %s;" % Naming.exc_lineno_name)
4657 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4658 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4659 code.putln(exc_var_init_zero)
4660 else:
4661 exc_var_init_zero = None
4662 code.use_label(catch_label)
4663 code.putln(
4664 "__pyx_why = 0; goto %s;" % catch_label)
4665 for i in cases_used:
4666 new_label = new_labels[i]
4667 #if new_label and new_label != "<try>":
4668 if new_label == new_error_label and self.preserve_exception:
4669 self.put_error_catcher(code,
4670 new_error_label, i+1, catch_label, temps_to_clean_up)
4671 else:
4672 code.put('%s: ' % new_label)
4673 if exc_var_init_zero:
4674 code.putln(exc_var_init_zero)
4675 code.putln("__pyx_why = %s; goto %s;" % (
4676 i+1,
4677 catch_label))
4678 code.put_label(catch_label)
4679 code.set_all_labels(old_labels)
4680 if error_label_used:
4681 code.new_error_label()
4682 finally_error_label = code.error_label
4683 self.finally_clause.generate_execution_code(code)
4684 if error_label_used:
4685 if finally_error_label in code.labels_used and self.preserve_exception:
4686 over_label = code.new_label()
4687 code.put_goto(over_label);
4688 code.put_label(finally_error_label)
4689 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4690 for var in Naming.exc_vars:
4691 code.putln("Py_XDECREF(%s);" % var)
4692 code.putln("}")
4693 code.put_goto(old_error_label)
4694 code.put_label(over_label)
4695 code.error_label = old_error_label
4696 if cases_used:
4697 code.putln(
4698 "switch (__pyx_why) {")
4699 for i in cases_used:
4700 old_label = old_labels[i]
4701 if old_label == old_error_label and self.preserve_exception:
4702 self.put_error_uncatcher(code, i+1, old_error_label)
4703 else:
4704 code.use_label(old_label)
4705 code.putln(
4706 "case %s: goto %s;" % (
4707 i+1,
4708 old_label))
4709 code.putln(
4710 "}")
4711 code.putln(
4712 "}")
4714 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4715 code.globalstate.use_utility_code(restore_exception_utility_code)
4716 code.putln(
4717 "%s: {" %
4718 error_label)
4719 code.putln(
4720 "__pyx_why = %s;" %
4721 i)
4722 for temp_name, type in temps_to_clean_up:
4723 code.put_xdecref_clear(temp_name, type)
4724 code.putln(
4725 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4726 Naming.exc_vars)
4727 code.putln(
4728 "%s = %s;" % (
4729 Naming.exc_lineno_name, Naming.lineno_cname))
4730 code.put_goto(catch_label)
4731 code.putln("}")
4733 def put_error_uncatcher(self, code, i, error_label):
4734 code.globalstate.use_utility_code(restore_exception_utility_code)
4735 code.putln(
4736 "case %s: {" %
4737 i)
4738 code.putln(
4739 "__Pyx_ErrRestore(%s, %s, %s);" %
4740 Naming.exc_vars)
4741 code.putln(
4742 "%s = %s;" % (
4743 Naming.lineno_cname, Naming.exc_lineno_name))
4744 for var in Naming.exc_vars:
4745 code.putln(
4746 "%s = 0;" %
4747 var)
4748 code.put_goto(error_label)
4749 code.putln(
4750 "}")
4752 def annotate(self, code):
4753 self.body.annotate(code)
4754 self.finally_clause.annotate(code)
4757 class GILStatNode(TryFinallyStatNode):
4758 # 'with gil' or 'with nogil' statement
4759 #
4760 # state string 'gil' or 'nogil'
4762 # child_attrs = []
4764 preserve_exception = 0
4766 def __init__(self, pos, state, body):
4767 self.state = state
4768 TryFinallyStatNode.__init__(self, pos,
4769 body = body,
4770 finally_clause = GILExitNode(pos, state = state))
4772 def analyse_expressions(self, env):
4773 env.use_utility_code(force_init_threads_utility_code)
4774 was_nogil = env.nogil
4775 env.nogil = 1
4776 TryFinallyStatNode.analyse_expressions(self, env)
4777 env.nogil = was_nogil
4779 nogil_check = None
4781 def generate_execution_code(self, code):
4782 code.mark_pos(self.pos)
4783 if self.state == 'gil':
4784 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4785 else:
4786 code.putln("{ PyThreadState *_save;")
4787 code.putln("Py_UNBLOCK_THREADS")
4788 TryFinallyStatNode.generate_execution_code(self, code)
4789 code.putln("}")
4792 class GILExitNode(StatNode):
4793 # Used as the 'finally' block in a GILStatNode
4794 #
4795 # state string 'gil' or 'nogil'
4797 child_attrs = []
4799 def analyse_expressions(self, env):
4800 pass
4802 def generate_execution_code(self, code):
4803 if self.state == 'gil':
4804 code.putln("PyGILState_Release();")
4805 else:
4806 code.putln("Py_BLOCK_THREADS")
4809 class CImportStatNode(StatNode):
4810 # cimport statement
4811 #
4812 # module_name string Qualified name of module being imported
4813 # as_name string or None Name specified in "as" clause, if any
4815 child_attrs = []
4817 def analyse_declarations(self, env):
4818 if not env.is_module_scope:
4819 error(self.pos, "cimport only allowed at module level")
4820 return
4821 module_scope = env.find_module(self.module_name, self.pos)
4822 if "." in self.module_name:
4823 names = [EncodedString(name) for name in self.module_name.split(".")]
4824 top_name = names[0]
4825 top_module_scope = env.context.find_submodule(top_name)
4826 module_scope = top_module_scope
4827 for name in names[1:]:
4828 submodule_scope = module_scope.find_submodule(name)
4829 module_scope.declare_module(name, submodule_scope, self.pos)
4830 module_scope = submodule_scope
4831 if self.as_name:
4832 env.declare_module(self.as_name, module_scope, self.pos)
4833 else:
4834 env.declare_module(top_name, top_module_scope, self.pos)
4835 else:
4836 name = self.as_name or self.module_name
4837 env.declare_module(name, module_scope, self.pos)
4839 def analyse_expressions(self, env):
4840 pass
4842 def generate_execution_code(self, code):
4843 pass
4846 class FromCImportStatNode(StatNode):
4847 # from ... cimport statement
4848 #
4849 # module_name string Qualified name of module
4850 # imported_names [(pos, name, as_name, kind)] Names to be imported
4852 child_attrs = []
4854 def analyse_declarations(self, env):
4855 if not env.is_module_scope:
4856 error(self.pos, "cimport only allowed at module level")
4857 return
4858 module_scope = env.find_module(self.module_name, self.pos)
4859 env.add_imported_module(module_scope)
4860 for pos, name, as_name, kind in self.imported_names:
4861 if name == "*":
4862 for local_name, entry in module_scope.entries.items():
4863 env.add_imported_entry(local_name, entry, pos)
4864 else:
4865 entry = module_scope.lookup(name)
4866 if entry:
4867 if kind and not self.declaration_matches(entry, kind):
4868 entry.redeclared(pos)
4869 else:
4870 if kind == 'struct' or kind == 'union':
4871 entry = module_scope.declare_struct_or_union(name,
4872 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4873 elif kind == 'class':
4874 entry = module_scope.declare_c_class(name, pos = pos,
4875 module_name = self.module_name)
4876 else:
4877 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4878 if submodule_scope.parent_module is module_scope:
4879 env.declare_module(as_name or name, submodule_scope, self.pos)
4880 else:
4881 error(pos, "Name '%s' not declared in module '%s'"
4882 % (name, self.module_name))
4884 if entry:
4885 local_name = as_name or name
4886 env.add_imported_entry(local_name, entry, pos)
4888 def declaration_matches(self, entry, kind):
4889 if not entry.is_type:
4890 return 0
4891 type = entry.type
4892 if kind == 'class':
4893 if not type.is_extension_type:
4894 return 0
4895 else:
4896 if not type.is_struct_or_union:
4897 return 0
4898 if kind != type.kind:
4899 return 0
4900 return 1
4902 def analyse_expressions(self, env):
4903 pass
4905 def generate_execution_code(self, code):
4906 pass
4909 class FromImportStatNode(StatNode):
4910 # from ... import statement
4911 #
4912 # module ImportNode
4913 # items [(string, NameNode)]
4914 # interned_items [(string, NameNode, ExprNode)]
4915 # item PyTempNode used internally
4916 # import_star boolean used internally
4918 child_attrs = ["module"]
4919 import_star = 0
4921 def analyse_declarations(self, env):
4922 for name, target in self.items:
4923 if name == "*":
4924 if not env.is_module_scope:
4925 error(self.pos, "import * only allowed at module level")
4926 return
4927 env.has_import_star = 1
4928 self.import_star = 1
4929 else:
4930 target.analyse_target_declaration(env)
4932 def analyse_expressions(self, env):
4933 import ExprNodes
4934 self.module.analyse_expressions(env)
4935 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
4936 self.interned_items = []
4937 for name, target in self.items:
4938 if name == '*':
4939 for _, entry in env.entries.items():
4940 if not entry.is_type and entry.type.is_extension_type:
4941 env.use_utility_code(ExprNodes.type_test_utility_code)
4942 break
4943 else:
4944 entry = env.lookup(target.name)
4945 if (entry.is_type and
4946 entry.type.name == name and
4947 entry.type.module_name == self.module.module_name.value):
4948 continue # already cimported
4949 target.analyse_target_expression(env, None)
4950 if target.type is py_object_type:
4951 coerced_item = None
4952 else:
4953 coerced_item = self.item.coerce_to(target.type, env)
4954 self.interned_items.append(
4955 (name, target, coerced_item))
4957 def generate_execution_code(self, code):
4958 self.module.generate_evaluation_code(code)
4959 if self.import_star:
4960 code.putln(
4961 'if (%s(%s) < 0) %s;' % (
4962 Naming.import_star,
4963 self.module.py_result(),
4964 code.error_goto(self.pos)))
4965 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
4966 self.item.set_cname(item_temp)
4967 for name, target, coerced_item in self.interned_items:
4968 cname = code.intern_identifier(name)
4969 code.putln(
4970 '%s = PyObject_GetAttr(%s, %s); %s' % (
4971 item_temp,
4972 self.module.py_result(),
4973 cname,
4974 code.error_goto_if_null(item_temp, self.pos)))
4975 code.put_gotref(item_temp)
4976 if coerced_item is None:
4977 target.generate_assignment_code(self.item, code)
4978 else:
4979 coerced_item.allocate_temp_result(code)
4980 coerced_item.generate_result_code(code)
4981 target.generate_assignment_code(coerced_item, code)
4982 code.put_decref_clear(item_temp, py_object_type)
4983 code.funcstate.release_temp(item_temp)
4984 self.module.generate_disposal_code(code)
4985 self.module.free_temps(code)
4989 #------------------------------------------------------------------------------------
4990 #
4991 # Runtime support code
4992 #
4993 #------------------------------------------------------------------------------------
4995 utility_function_predeclarations = \
4996 """
4997 #ifndef CYTHON_INLINE
4998 #if defined(__GNUC__)
4999 #define CYTHON_INLINE __inline__
5000 #elif defined(_MSC_VER)
5001 #define CYTHON_INLINE __inline
5002 #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
5003 #define CYTHON_INLINE inline
5004 #else
5005 #define CYTHON_INLINE
5006 #endif
5007 #endif
5009 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*/
5011 """
5013 if Options.gcc_branch_hints:
5014 branch_prediction_macros = \
5015 """
5016 #ifdef __GNUC__
5017 /* Test for GCC > 2.95 */
5018 #if __GNUC__ > 2 || \
5019 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
5020 #define likely(x) __builtin_expect(!!(x), 1)
5021 #define unlikely(x) __builtin_expect(!!(x), 0)
5022 #else /* __GNUC__ > 2 ... */
5023 #define likely(x) (x)
5024 #define unlikely(x) (x)
5025 #endif /* __GNUC__ > 2 ... */
5026 #else /* __GNUC__ */
5027 #define likely(x) (x)
5028 #define unlikely(x) (x)
5029 #endif /* __GNUC__ */
5030 """
5031 else:
5032 branch_prediction_macros = \
5033 """
5034 #define likely(x) (x)
5035 #define unlikely(x) (x)
5036 """
5038 #get_name_predeclaration = \
5039 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
5041 #get_name_interned_predeclaration = \
5042 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
5044 #------------------------------------------------------------------------------------
5046 printing_utility_code = UtilityCode(
5047 proto = """
5048 static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/
5049 #if PY_MAJOR_VERSION >= 3
5050 static PyObject* %s = 0;
5051 static PyObject* %s = 0;
5052 #endif
5053 """ % (Naming.print_function, Naming.print_function_kwargs),
5054 impl = r"""
5055 #if PY_MAJOR_VERSION < 3
5056 static PyObject *__Pyx_GetStdout(void) {
5057 PyObject *f = PySys_GetObject((char *)"stdout");
5058 if (!f) {
5059 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
5060 }
5061 return f;
5062 }
5064 static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
5065 PyObject* v;
5066 int i;
5068 if (!f) {
5069 if (!(f = __Pyx_GetStdout()))
5070 return -1;
5071 }
5072 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
5073 if (PyFile_SoftSpace(f, 1)) {
5074 if (PyFile_WriteString(" ", f) < 0)
5075 return -1;
5076 }
5077 v = PyTuple_GET_ITEM(arg_tuple, i);
5078 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
5079 return -1;
5080 if (PyString_Check(v)) {
5081 char *s = PyString_AsString(v);
5082 Py_ssize_t len = PyString_Size(v);
5083 if (len > 0 &&
5084 isspace(Py_CHARMASK(s[len-1])) &&
5085 s[len-1] != ' ')
5086 PyFile_SoftSpace(f, 0);
5087 }
5088 }
5089 if (newline) {
5090 if (PyFile_WriteString("\n", f) < 0)
5091 return -1;
5092 PyFile_SoftSpace(f, 0);
5093 }
5094 return 0;
5095 }
5097 #else /* Python 3 has a print function */
5099 static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
5100 PyObject* kwargs = 0;
5101 PyObject* result = 0;
5102 PyObject* end_string;
5103 if (!%(PRINT_FUNCTION)s) {
5104 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
5105 if (!%(PRINT_FUNCTION)s)
5106 return -1;
5107 }
5108 if (stream) {
5109 kwargs = PyDict_New();
5110 if (unlikely(!kwargs))
5111 return -1;
5112 if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0))
5113 goto bad;
5114 }
5115 }
5116 if (!newline) {
5117 if (!kwargs)
5118 kwargs = %(PRINT_KWARGS)s;
5119 if (!kwargs) {
5120 %(PRINT_KWARGS)s = PyDict_New();
5121 if unlikely((!%(PRINT_KWARGS)s))
5122 return -1;
5123 kwargs = %(PRINT_KWARGS)s;
5124 }
5125 end_string = PyUnicode_FromStringAndSize(" ", 1);
5126 if (unlikely(!end_string))
5127 goto bad;
5128 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
5129 Py_DECREF(end_string);
5130 goto bad;
5131 }
5132 Py_DECREF(end_string);
5133 }
5134 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
5135 if (unlikely(kwargs) && (kwargs != %(PRINT_FUNCTION)s))
5136 Py_DECREF(kwargs);
5137 if (!result)
5138 return -1;
5139 Py_DECREF(result);
5140 return 0;
5141 bad:
5142 if (kwargs != %(PRINT_FUNCTION)s)
5143 Py_XDECREF(kwargs);
5144 return -1;
5145 }
5147 #endif
5148 """ % {'BUILTINS' : Naming.builtins_cname,
5149 'PRINT_FUNCTION' : Naming.print_function,
5150 'PRINT_KWARGS' : Naming.print_function_kwargs}
5151 )
5154 printing_one_utility_code = UtilityCode(
5155 proto = """
5156 static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/
5157 """,
5158 impl = r"""
5159 #if PY_MAJOR_VERSION < 3
5161 static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
5162 if (!f) {
5163 if (!(f = __Pyx_GetStdout()))
5164 return -1;
5165 }
5166 if (PyFile_SoftSpace(f, 0)) {
5167 if (PyFile_WriteString(" ", f) < 0)
5168 return -1;
5169 }
5170 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5171 return -1;
5172 if (PyFile_WriteString("\n", f) < 0)
5173 return -1;
5174 return 0;
5175 /* the line below is just to avoid compiler
5176 * compiler warnings about unused functions */
5177 return __Pyx_Print(f, NULL, 0);
5178 }
5180 #else /* Python 3 has a print function */
5182 static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
5183 int res;
5184 PyObject* arg_tuple = PyTuple_New(1);
5185 if (unlikely(!arg_tuple))
5186 return -1;
5187 Py_INCREF(o);
5188 PyTuple_SET_ITEM(arg_tuple, 0, o);
5189 res = __Pyx_Print(stream, arg_tuple, 1);
5190 Py_DECREF(arg_tuple);
5191 return res;
5192 }
5194 #endif
5195 """,
5196 requires=[printing_utility_code])
5200 #------------------------------------------------------------------------------------
5202 # Exception raising code
5203 #
5204 # Exceptions are raised by __Pyx_Raise() and stored as plain
5205 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5206 # 'except' statement, curexc_* is moved over to exc_* by
5207 # __Pyx_GetException()
5209 restore_exception_utility_code = UtilityCode(
5210 proto = """
5211 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5212 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5213 """,
5214 impl = """
5215 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5216 PyObject *tmp_type, *tmp_value, *tmp_tb;
5217 PyThreadState *tstate = PyThreadState_GET();
5219 tmp_type = tstate->curexc_type;
5220 tmp_value = tstate->curexc_value;
5221 tmp_tb = tstate->curexc_traceback;
5222 tstate->curexc_type = type;
5223 tstate->curexc_value = value;
5224 tstate->curexc_traceback = tb;
5225 Py_XDECREF(tmp_type);
5226 Py_XDECREF(tmp_value);
5227 Py_XDECREF(tmp_tb);
5228 }
5230 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5231 PyThreadState *tstate = PyThreadState_GET();
5232 *type = tstate->curexc_type;
5233 *value = tstate->curexc_value;
5234 *tb = tstate->curexc_traceback;
5236 tstate->curexc_type = 0;
5237 tstate->curexc_value = 0;
5238 tstate->curexc_traceback = 0;
5239 }
5241 """)
5243 # The following function is based on do_raise() from ceval.c. There
5244 # are separate versions for Python2 and Python3 as exception handling
5245 # has changed quite a lot between the two versions.
5247 raise_utility_code = UtilityCode(
5248 proto = """
5249 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5250 """,
5251 impl = """
5252 #if PY_MAJOR_VERSION < 3
5253 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5254 Py_XINCREF(type);
5255 Py_XINCREF(value);
5256 Py_XINCREF(tb);
5257 /* First, check the traceback argument, replacing None with NULL. */
5258 if (tb == Py_None) {
5259 Py_DECREF(tb);
5260 tb = 0;
5261 }
5262 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5263 PyErr_SetString(PyExc_TypeError,
5264 "raise: arg 3 must be a traceback or None");
5265 goto raise_error;
5266 }
5267 /* Next, replace a missing value with None */
5268 if (value == NULL) {
5269 value = Py_None;
5270 Py_INCREF(value);
5271 }
5272 #if PY_VERSION_HEX < 0x02050000
5273 if (!PyClass_Check(type))
5274 #else
5275 if (!PyType_Check(type))
5276 #endif
5277 {
5278 /* Raising an instance. The value should be a dummy. */
5279 if (value != Py_None) {
5280 PyErr_SetString(PyExc_TypeError,
5281 "instance exception may not have a separate value");
5282 goto raise_error;
5283 }
5284 /* Normalize to raise <class>, <instance> */
5285 Py_DECREF(value);
5286 value = type;
5287 #if PY_VERSION_HEX < 0x02050000
5288 if (PyInstance_Check(type)) {
5289 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5290 Py_INCREF(type);
5291 }
5292 else {
5293 type = 0;
5294 PyErr_SetString(PyExc_TypeError,
5295 "raise: exception must be an old-style class or instance");
5296 goto raise_error;
5297 }
5298 #else
5299 type = (PyObject*) Py_TYPE(type);
5300 Py_INCREF(type);
5301 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5302 PyErr_SetString(PyExc_TypeError,
5303 "raise: exception class must be a subclass of BaseException");
5304 goto raise_error;
5305 }
5306 #endif
5307 }
5309 __Pyx_ErrRestore(type, value, tb);
5310 return;
5311 raise_error:
5312 Py_XDECREF(value);
5313 Py_XDECREF(type);
5314 Py_XDECREF(tb);
5315 return;
5316 }
5318 #else /* Python 3+ */
5320 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5321 if (tb == Py_None) {
5322 tb = 0;
5323 } else if (tb && !PyTraceBack_Check(tb)) {
5324 PyErr_SetString(PyExc_TypeError,
5325 "raise: arg 3 must be a traceback or None");
5326 goto bad;
5327 }
5328 if (value == Py_None)
5329 value = 0;
5331 if (PyExceptionInstance_Check(type)) {
5332 if (value) {
5333 PyErr_SetString(PyExc_TypeError,
5334 "instance exception may not have a separate value");
5335 goto bad;
5336 }
5337 value = type;
5338 type = (PyObject*) Py_TYPE(value);
5339 } else if (!PyExceptionClass_Check(type)) {
5340 PyErr_SetString(PyExc_TypeError,
5341 "raise: exception class must be a subclass of BaseException");
5342 goto bad;
5343 }
5345 PyErr_SetObject(type, value);
5347 if (tb) {
5348 PyThreadState *tstate = PyThreadState_GET();
5349 PyObject* tmp_tb = tstate->curexc_traceback;
5350 if (tb != tmp_tb) {
5351 Py_INCREF(tb);
5352 tstate->curexc_traceback = tb;
5353 Py_XDECREF(tmp_tb);
5354 }
5355 }
5357 bad:
5358 return;
5359 }
5360 #endif
5361 """,
5362 requires=[restore_exception_utility_code])
5364 #------------------------------------------------------------------------------------
5366 get_exception_utility_code = UtilityCode(
5367 proto = """
5368 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5369 """,
5370 impl = """
5371 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5372 PyObject *local_type, *local_value, *local_tb;
5373 PyObject *tmp_type, *tmp_value, *tmp_tb;
5374 PyThreadState *tstate = PyThreadState_GET();
5375 local_type = tstate->curexc_type;
5376 local_value = tstate->curexc_value;
5377 local_tb = tstate->curexc_traceback;
5378 tstate->curexc_type = 0;
5379 tstate->curexc_value = 0;
5380 tstate->curexc_traceback = 0;
5381 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5382 if (unlikely(tstate->curexc_type))
5383 goto bad;
5384 #if PY_MAJOR_VERSION >= 3
5385 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5386 goto bad;
5387 #endif
5388 *type = local_type;
5389 *value = local_value;
5390 *tb = local_tb;
5391 Py_INCREF(local_type);
5392 Py_INCREF(local_value);
5393 Py_INCREF(local_tb);
5394 tmp_type = tstate->exc_type;
5395 tmp_value = tstate->exc_value;
5396 tmp_tb = tstate->exc_traceback;
5397 tstate->exc_type = local_type;
5398 tstate->exc_value = local_value;
5399 tstate->exc_traceback = local_tb;
5400 /* Make sure tstate is in a consistent state when we XDECREF
5401 these objects (XDECREF may run arbitrary code). */
5402 Py_XDECREF(tmp_type);
5403 Py_XDECREF(tmp_value);
5404 Py_XDECREF(tmp_tb);
5405 return 0;
5406 bad:
5407 *type = 0;
5408 *value = 0;
5409 *tb = 0;
5410 Py_XDECREF(local_type);
5411 Py_XDECREF(local_value);
5412 Py_XDECREF(local_tb);
5413 return -1;
5414 }
5416 """)
5418 #------------------------------------------------------------------------------------
5420 get_exception_tuple_utility_code = UtilityCode(proto="""
5421 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5422 """,
5423 # I doubt that calling __Pyx_GetException() here is correct as it moves
5424 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5425 # exception handlers later on from receiving it.
5426 impl = """
5427 static PyObject *__Pyx_GetExceptionTuple(void) {
5428 PyObject *type = NULL, *value = NULL, *tb = NULL;
5429 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5430 PyObject* exc_info = PyTuple_New(3);
5431 if (exc_info) {
5432 Py_INCREF(type);
5433 Py_INCREF(value);
5434 Py_INCREF(tb);
5435 PyTuple_SET_ITEM(exc_info, 0, type);
5436 PyTuple_SET_ITEM(exc_info, 1, value);
5437 PyTuple_SET_ITEM(exc_info, 2, tb);
5438 return exc_info;
5439 }
5440 }
5441 return NULL;
5442 }
5443 """,
5444 requires=[get_exception_utility_code])
5446 #------------------------------------------------------------------------------------
5448 reset_exception_utility_code = UtilityCode(
5449 proto = """
5450 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5451 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5452 """,
5453 impl = """
5454 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5455 PyThreadState *tstate = PyThreadState_GET();
5456 *type = tstate->exc_type;
5457 *value = tstate->exc_value;
5458 *tb = tstate->exc_traceback;
5459 Py_XINCREF(*type);
5460 Py_XINCREF(*value);
5461 Py_XINCREF(*tb);
5462 }
5464 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5465 PyObject *tmp_type, *tmp_value, *tmp_tb;
5466 PyThreadState *tstate = PyThreadState_GET();
5467 tmp_type = tstate->exc_type;
5468 tmp_value = tstate->exc_value;
5469 tmp_tb = tstate->exc_traceback;
5470 tstate->exc_type = type;
5471 tstate->exc_value = value;
5472 tstate->exc_traceback = tb;
5473 Py_XDECREF(tmp_type);
5474 Py_XDECREF(tmp_value);
5475 Py_XDECREF(tmp_tb);
5476 }
5477 """)
5479 #------------------------------------------------------------------------------------
5481 arg_type_test_utility_code = UtilityCode(
5482 proto = """
5483 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5484 const char *name, int exact); /*proto*/
5485 """,
5486 impl = """
5487 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5488 const char *name, int exact)
5489 {
5490 if (!type) {
5491 PyErr_Format(PyExc_SystemError, "Missing type object");
5492 return 0;
5493 }
5494 if (none_allowed && obj == Py_None) return 1;
5495 else if (exact) {
5496 if (Py_TYPE(obj) == type) return 1;
5497 }
5498 else {
5499 if (PyObject_TypeCheck(obj, type)) return 1;
5500 }
5501 PyErr_Format(PyExc_TypeError,
5502 "Argument '%s' has incorrect type (expected %s, got %s)",
5503 name, type->tp_name, Py_TYPE(obj)->tp_name);
5504 return 0;
5505 }
5506 """)
5508 #------------------------------------------------------------------------------------
5509 #
5510 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5511 # many or too few positional arguments were found. This handles
5512 # Py_ssize_t formatting correctly.
5514 raise_argtuple_invalid_utility_code = UtilityCode(
5515 proto = """
5516 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5517 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5518 """,
5519 impl = """
5520 static void __Pyx_RaiseArgtupleInvalid(
5521 const char* func_name,
5522 int exact,
5523 Py_ssize_t num_min,
5524 Py_ssize_t num_max,
5525 Py_ssize_t num_found)
5526 {
5527 Py_ssize_t num_expected;
5528 const char *number, *more_or_less;
5530 if (num_found < num_min) {
5531 num_expected = num_min;
5532 more_or_less = "at least";
5533 } else {
5534 num_expected = num_max;
5535 more_or_less = "at most";
5536 }
5537 if (exact) {
5538 more_or_less = "exactly";
5539 }
5540 number = (num_expected == 1) ? "" : "s";
5541 PyErr_Format(PyExc_TypeError,
5542 #if PY_VERSION_HEX < 0x02050000
5543 "%s() takes %s %d positional argument%s (%d given)",
5544 #else
5545 "%s() takes %s %zd positional argument%s (%zd given)",
5546 #endif
5547 func_name, more_or_less, num_expected, number, num_found);
5548 }
5549 """)
5551 raise_keyword_required_utility_code = UtilityCode(
5552 proto = """
5553 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5554 """,
5555 impl = """
5556 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(
5557 const char* func_name,
5558 PyObject* kw_name)
5559 {
5560 PyErr_Format(PyExc_TypeError,
5561 #if PY_MAJOR_VERSION >= 3
5562 "%s() needs keyword-only argument %U", func_name, kw_name);
5563 #else
5564 "%s() needs keyword-only argument %s", func_name,
5565 PyString_AS_STRING(kw_name));
5566 #endif
5567 }
5568 """)
5570 raise_double_keywords_utility_code = UtilityCode(
5571 proto = """
5572 static void __Pyx_RaiseDoubleKeywordsError(
5573 const char* func_name, PyObject* kw_name); /*proto*/
5574 """,
5575 impl = """
5576 static void __Pyx_RaiseDoubleKeywordsError(
5577 const char* func_name,
5578 PyObject* kw_name)
5579 {
5580 PyErr_Format(PyExc_TypeError,
5581 #if PY_MAJOR_VERSION >= 3
5582 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5583 #else
5584 "%s() got multiple values for keyword argument '%s'", func_name,
5585 PyString_AS_STRING(kw_name));
5586 #endif
5587 }
5588 """)
5590 #------------------------------------------------------------------------------------
5591 #
5592 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5593 # were passed to a function, or if any keywords were passed to a
5594 # function that does not accept them.
5596 keyword_string_check_utility_code = UtilityCode(
5597 proto = """
5598 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5599 const char* function_name, int kw_allowed); /*proto*/
5600 """,
5601 impl = """
5602 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
5603 PyObject *kwdict,
5604 const char* function_name,
5605 int kw_allowed)
5606 {
5607 PyObject* key = 0;
5608 Py_ssize_t pos = 0;
5609 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5610 #if PY_MAJOR_VERSION < 3
5611 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5612 #else
5613 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5614 #endif
5615 goto invalid_keyword_type;
5616 }
5617 if ((!kw_allowed) && unlikely(key))
5618 goto invalid_keyword;
5619 return 1;
5620 invalid_keyword_type:
5621 PyErr_Format(PyExc_TypeError,
5622 "%s() keywords must be strings", function_name);
5623 return 0;
5624 invalid_keyword:
5625 PyErr_Format(PyExc_TypeError,
5626 #if PY_MAJOR_VERSION < 3
5627 "%s() got an unexpected keyword argument '%s'",
5628 function_name, PyString_AsString(key));
5629 #else
5630 "%s() got an unexpected keyword argument '%U'",
5631 function_name, key);
5632 #endif
5633 return 0;
5634 }
5635 """)
5637 #------------------------------------------------------------------------------------
5638 #
5639 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5640 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5641 # keywords will raise an invalid keyword error.
5642 #
5643 # Three kinds of errors are checked: 1) non-string keywords, 2)
5644 # unexpected keywords and 3) overlap with positional arguments.
5645 #
5646 # If num_posargs is greater 0, it denotes the number of positional
5647 # arguments that were passed and that must therefore not appear
5648 # amongst the keywords as well.
5649 #
5650 # This method does not check for required keyword arguments.
5651 #
5653 parse_keywords_utility_code = UtilityCode(
5654 proto = """
5655 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5656 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5657 const char* function_name); /*proto*/
5658 """,
5659 impl = """
5660 static int __Pyx_ParseOptionalKeywords(
5661 PyObject *kwds,
5662 PyObject **argnames[],
5663 PyObject *kwds2,
5664 PyObject *values[],
5665 Py_ssize_t num_pos_args,
5666 const char* function_name)
5667 {
5668 PyObject *key = 0, *value = 0;
5669 Py_ssize_t pos = 0;
5670 PyObject*** name;
5671 PyObject*** first_kw_arg = argnames + num_pos_args;
5673 while (PyDict_Next(kwds, &pos, &key, &value)) {
5674 name = first_kw_arg;
5675 while (*name && (**name != key)) name++;
5676 if (*name) {
5677 values[name-argnames] = value;
5678 } else {
5679 #if PY_MAJOR_VERSION < 3
5680 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5681 #else
5682 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5683 #endif
5684 goto invalid_keyword_type;
5685 } else {
5686 for (name = first_kw_arg; *name; name++) {
5687 #if PY_MAJOR_VERSION >= 3
5688 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5689 PyUnicode_Compare(**name, key) == 0) break;
5690 #else
5691 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5692 _PyString_Eq(**name, key)) break;
5693 #endif
5694 }
5695 if (*name) {
5696 values[name-argnames] = value;
5697 } else {
5698 /* unexpected keyword found */
5699 for (name=argnames; name != first_kw_arg; name++) {
5700 if (**name == key) goto arg_passed_twice;
5701 #if PY_MAJOR_VERSION >= 3
5702 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5703 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5704 #else
5705 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5706 _PyString_Eq(**name, key)) goto arg_passed_twice;
5707 #endif
5708 }
5709 if (kwds2) {
5710 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5711 } else {
5712 goto invalid_keyword;
5713 }
5714 }
5715 }
5716 }
5717 }
5718 return 0;
5719 arg_passed_twice:
5720 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5721 goto bad;
5722 invalid_keyword_type:
5723 PyErr_Format(PyExc_TypeError,
5724 "%s() keywords must be strings", function_name);
5725 goto bad;
5726 invalid_keyword:
5727 PyErr_Format(PyExc_TypeError,
5728 #if PY_MAJOR_VERSION < 3
5729 "%s() got an unexpected keyword argument '%s'",
5730 function_name, PyString_AsString(key));
5731 #else
5732 "%s() got an unexpected keyword argument '%U'",
5733 function_name, key);
5734 #endif
5735 bad:
5736 return -1;
5737 }
5738 """)
5740 #------------------------------------------------------------------------------------
5742 traceback_utility_code = UtilityCode(
5743 proto = """
5744 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5745 """,
5746 impl = """
5747 #include "compile.h"
5748 #include "frameobject.h"
5749 #include "traceback.h"
5751 static void __Pyx_AddTraceback(const char *funcname) {
5752 PyObject *py_srcfile = 0;
5753 PyObject *py_funcname = 0;
5754 PyObject *py_globals = 0;
5755 PyCodeObject *py_code = 0;
5756 PyFrameObject *py_frame = 0;
5758 #if PY_MAJOR_VERSION < 3
5759 py_srcfile = PyString_FromString(%(FILENAME)s);
5760 #else
5761 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5762 #endif
5763 if (!py_srcfile) goto bad;
5764 if (%(CLINENO)s) {
5765 #if PY_MAJOR_VERSION < 3
5766 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5767 #else
5768 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5769 #endif
5770 }
5771 else {
5772 #if PY_MAJOR_VERSION < 3
5773 py_funcname = PyString_FromString(funcname);
5774 #else
5775 py_funcname = PyUnicode_FromString(funcname);
5776 #endif
5777 }
5778 if (!py_funcname) goto bad;
5779 py_globals = PyModule_GetDict(%(GLOBALS)s);
5780 if (!py_globals) goto bad;
5781 py_code = PyCode_New(
5782 0, /*int argcount,*/
5783 #if PY_MAJOR_VERSION >= 3
5784 0, /*int kwonlyargcount,*/
5785 #endif
5786 0, /*int nlocals,*/
5787 0, /*int stacksize,*/
5788 0, /*int flags,*/
5789 %(EMPTY_BYTES)s, /*PyObject *code,*/
5790 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5791 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5792 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5793 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5794 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5795 py_srcfile, /*PyObject *filename,*/
5796 py_funcname, /*PyObject *name,*/
5797 %(LINENO)s, /*int firstlineno,*/
5798 %(EMPTY_BYTES)s /*PyObject *lnotab*/
5799 );
5800 if (!py_code) goto bad;
5801 py_frame = PyFrame_New(
5802 PyThreadState_GET(), /*PyThreadState *tstate,*/
5803 py_code, /*PyCodeObject *code,*/
5804 py_globals, /*PyObject *globals,*/
5805 0 /*PyObject *locals*/
5806 );
5807 if (!py_frame) goto bad;
5808 py_frame->f_lineno = %(LINENO)s;
5809 PyTraceBack_Here(py_frame);
5810 bad:
5811 Py_XDECREF(py_srcfile);
5812 Py_XDECREF(py_funcname);
5813 Py_XDECREF(py_code);
5814 Py_XDECREF(py_frame);
5815 }
5816 """ % {
5817 'FILENAME': Naming.filename_cname,
5818 'LINENO': Naming.lineno_cname,
5819 'CFILENAME': Naming.cfilenm_cname,
5820 'CLINENO': Naming.clineno_cname,
5821 'GLOBALS': Naming.module_cname,
5822 'EMPTY_TUPLE' : Naming.empty_tuple,
5823 'EMPTY_BYTES' : Naming.empty_bytes,
5824 })
5826 #------------------------------------------------------------------------------------
5828 unraisable_exception_utility_code = UtilityCode(
5829 proto = """
5830 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5831 """,
5832 impl = """
5833 static void __Pyx_WriteUnraisable(const char *name) {
5834 PyObject *old_exc, *old_val, *old_tb;
5835 PyObject *ctx;
5836 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5837 #if PY_MAJOR_VERSION < 3
5838 ctx = PyString_FromString(name);
5839 #else
5840 ctx = PyUnicode_FromString(name);
5841 #endif
5842 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5843 if (!ctx) {
5844 PyErr_WriteUnraisable(Py_None);
5845 } else {
5846 PyErr_WriteUnraisable(ctx);
5847 Py_DECREF(ctx);
5848 }
5849 }
5850 """,
5851 requires=[restore_exception_utility_code])
5853 #------------------------------------------------------------------------------------
5855 set_vtable_utility_code = UtilityCode(
5856 proto = """
5857 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5858 """,
5859 impl = """
5860 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5861 #if PY_VERSION_HEX < 0x03010000
5862 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
5863 #else
5864 PyObject *ob = PyCapsule_New(vtable, 0, 0);
5865 #endif
5866 if (!ob)
5867 goto bad;
5868 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
5869 goto bad;
5870 Py_DECREF(ob);
5871 return 0;
5872 bad:
5873 Py_XDECREF(ob);
5874 return -1;
5875 }
5876 """)
5878 #------------------------------------------------------------------------------------
5880 get_vtable_utility_code = UtilityCode(
5881 proto = """
5882 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5883 """,
5884 impl = r"""
5885 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5886 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5887 if (!ob)
5888 goto bad;
5889 #if PY_VERSION_HEX < 0x03010000
5890 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
5891 #else
5892 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
5893 #endif
5894 if (!*(void **)vtabptr)
5895 goto bad;
5896 Py_DECREF(ob);
5897 return 0;
5898 bad:
5899 Py_XDECREF(ob);
5900 return -1;
5901 }
5902 """)
5904 #------------------------------------------------------------------------------------
5906 init_string_tab_utility_code = UtilityCode(
5907 proto = """
5908 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5909 """,
5910 impl = """
5911 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5912 while (t->p) {
5913 #if PY_MAJOR_VERSION < 3
5914 if (t->is_unicode) {
5915 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5916 } else if (t->intern) {
5917 *t->p = PyString_InternFromString(t->s);
5918 } else {
5919 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5920 }
5921 #else /* Python 3+ has unicode identifiers */
5922 if (t->is_unicode | t->is_str) {
5923 if (t->intern) {
5924 *t->p = PyUnicode_InternFromString(t->s);
5925 } else if (t->encoding) {
5926 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
5927 } else {
5928 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5929 }
5930 } else {
5931 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5932 }
5933 #endif
5934 if (!*t->p)
5935 return -1;
5936 ++t;
5937 }
5938 return 0;
5939 }
5940 """)
5942 #------------------------------------------------------------------------------------
5944 force_init_threads_utility_code = UtilityCode(
5945 proto="""
5946 #ifndef __PYX_FORCE_INIT_THREADS
5947 #if PY_VERSION_HEX < 0x02040200
5948 #define __PYX_FORCE_INIT_THREADS 1
5949 #else
5950 #define __PYX_FORCE_INIT_THREADS 0
5951 #endif
5952 #endif
5953 """)
5955 #------------------------------------------------------------------------------------
5957 # Note that cPython ignores PyTrace_EXCEPTION,
5958 # but maybe some other profilers don't.
5960 profile_utility_code = UtilityCode(proto="""
5961 #ifndef CYTHON_PROFILE
5962 #define CYTHON_PROFILE 1
5963 #endif
5965 #ifndef CYTHON_PROFILE_REUSE_FRAME
5966 #define CYTHON_PROFILE_REUSE_FRAME 0
5967 #endif
5969 #if CYTHON_PROFILE
5971 #include "compile.h"
5972 #include "frameobject.h"
5973 #include "traceback.h"
5975 #if CYTHON_PROFILE_REUSE_FRAME
5976 #define CYTHON_FRAME_MODIFIER static
5977 #define CYTHON_FRAME_DEL
5978 #else
5979 #define CYTHON_FRAME_MODIFIER
5980 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
5981 #endif
5983 #define __Pyx_TraceDeclarations \\
5984 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
5985 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
5986 int __Pyx_use_tracing = 0;
5988 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
5989 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
5990 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
5991 }
5993 #define __Pyx_TraceException() \\
5994 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
5995 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
5996 if (exc_info) { \\
5997 PyThreadState_GET()->c_profilefunc( \\
5998 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
5999 Py_DECREF(exc_info); \\
6000 } \\
6001 }
6003 #define __Pyx_TraceReturn(result) \\
6004 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6005 PyThreadState_GET()->c_profilefunc( \\
6006 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
6007 CYTHON_FRAME_DEL; \\
6008 }
6010 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6011 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6013 #else
6015 #define __Pyx_TraceDeclarations
6016 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
6017 #define __Pyx_TraceException()
6018 #define __Pyx_TraceReturn(result)
6020 #endif /* CYTHON_PROFILE */
6021 """
6022 % {
6023 "FRAME": Naming.frame_cname,
6024 "FRAME_CODE": Naming.frame_code_cname,
6025 },
6026 impl = """
6028 #if CYTHON_PROFILE
6030 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
6031 PyFrameObject** frame,
6032 const char *funcname,
6033 const char *srcfile,
6034 int firstlineno) {
6035 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
6036 if (*code == NULL) {
6037 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
6038 if (*code == NULL) return 0;
6039 }
6040 *frame = PyFrame_New(
6041 PyThreadState_GET(), /*PyThreadState *tstate*/
6042 *code, /*PyCodeObject *code*/
6043 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
6044 0 /*PyObject *locals*/
6045 );
6046 if (*frame == NULL) return 0;
6047 }
6048 else {
6049 (*frame)->f_tstate = PyThreadState_GET();
6050 }
6051 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
6052 }
6054 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
6055 PyObject *py_srcfile = 0;
6056 PyObject *py_funcname = 0;
6057 PyCodeObject *py_code = 0;
6059 #if PY_MAJOR_VERSION < 3
6060 py_funcname = PyString_FromString(funcname);
6061 py_srcfile = PyString_FromString(srcfile);
6062 #else
6063 py_funcname = PyUnicode_FromString(funcname);
6064 py_srcfile = PyUnicode_FromString(srcfile);
6065 #endif
6066 if (!py_funcname | !py_srcfile) goto bad;
6068 py_code = PyCode_New(
6069 0, /*int argcount,*/
6070 #if PY_MAJOR_VERSION >= 3
6071 0, /*int kwonlyargcount,*/
6072 #endif
6073 0, /*int nlocals,*/
6074 0, /*int stacksize,*/
6075 0, /*int flags,*/
6076 %(EMPTY_BYTES)s, /*PyObject *code,*/
6077 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6078 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6079 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6080 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6081 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6082 py_srcfile, /*PyObject *filename,*/
6083 py_funcname, /*PyObject *name,*/
6084 firstlineno, /*int firstlineno,*/
6085 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6086 );
6088 bad:
6089 Py_XDECREF(py_srcfile);
6090 Py_XDECREF(py_funcname);
6092 return py_code;
6093 }
6095 #endif /* CYTHON_PROFILE */
6096 """ % {
6097 'EMPTY_TUPLE' : Naming.empty_tuple,
6098 'EMPTY_BYTES' : Naming.empty_bytes,
6099 "MODULE": Naming.module_cname,
6100 })
