Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 3659:63c67976adc6
Restore special method docstrings.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Sun Aug 15 00:12:36 2010 -0700 (21 months ago) |
| parents | c3a860d3dabd |
| children | 0b7f631ad65b |
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, ClosureScope, \
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 # or_none boolean Tagged with 'or None'
634 # accept_none boolean Resolved boolean for not_none/or_none
635 # default ExprNode or None
636 # default_value PyObjectConst constant for default value
637 # annotation ExprNode or None Py3 function arg annotation
638 # is_self_arg boolean Is the "self" arg of an extension type method
639 # is_type_arg boolean Is the "class" arg of an extension type classmethod
640 # is_kw_only boolean Is a keyword-only argument
642 child_attrs = ["base_type", "declarator", "default"]
644 is_self_arg = 0
645 is_type_arg = 0
646 is_generic = 1
647 type = None
648 name_declarator = None
649 default_value = None
650 annotation = None
652 def analyse(self, env, nonempty = 0):
653 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
654 if self.type is None:
655 # The parser may missinterpret names as types...
656 # We fix that here.
657 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
658 if nonempty:
659 self.declarator.name = self.base_type.name
660 self.base_type.name = None
661 self.base_type.is_basic_c_type = False
662 could_be_name = True
663 else:
664 could_be_name = False
665 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
666 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
667 self.declarator.name = self.base_type.arg_name
668 # The parser is unable to resolve the ambiguity of [] as part of the
669 # type (e.g. in buffers) or empty declarator (as with arrays).
670 # This is only arises for empty multi-dimensional arrays.
671 if (base_type.is_array
672 and isinstance(self.base_type, TemplatedTypeNode)
673 and isinstance(self.declarator, CArrayDeclaratorNode)):
674 declarator = self.declarator
675 while isinstance(declarator.base, CArrayDeclaratorNode):
676 declarator = declarator.base
677 declarator.base = self.base_type.array_declarator
678 base_type = base_type.base_type
679 return self.declarator.analyse(base_type, env, nonempty = nonempty)
680 else:
681 return self.name_declarator, self.type
683 def calculate_default_value_code(self, code):
684 if self.default_value is None:
685 if self.default:
686 if self.default.is_literal:
687 # will not output any code, just assign the result_code
688 self.default.generate_evaluation_code(code)
689 return self.type.cast_code(self.default.result())
690 self.default_value = code.get_argument_default_const(self.type)
691 return self.default_value
693 def annotate(self, code):
694 if self.default:
695 self.default.annotate(code)
698 class CBaseTypeNode(Node):
699 # Abstract base class for C base type nodes.
700 #
701 # Processing during analyse_declarations phase:
702 #
703 # analyse
704 # Returns the type.
706 pass
708 def analyse_as_type(self, env):
709 return self.analyse(env)
711 class CAnalysedBaseTypeNode(Node):
712 # type type
714 child_attrs = []
716 def analyse(self, env, could_be_name = False):
717 return self.type
719 class CSimpleBaseTypeNode(CBaseTypeNode):
720 # name string
721 # module_path [string] Qualifying name components
722 # is_basic_c_type boolean
723 # signed boolean
724 # longness integer
725 # complex boolean
726 # is_self_arg boolean Is self argument of C method
727 # ##is_type_arg boolean Is type argument of class method
729 child_attrs = []
730 arg_name = None # in case the argument name was interpreted as a type
732 def analyse(self, env, could_be_name = False):
733 # Return type descriptor.
734 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
735 type = None
736 if self.is_basic_c_type:
737 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
738 if not type:
739 error(self.pos, "Unrecognised type modifier combination")
740 elif self.name == "object" and not self.module_path:
741 type = py_object_type
742 elif self.name is None:
743 if self.is_self_arg and env.is_c_class_scope:
744 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
745 type = env.parent_type
746 ## elif self.is_type_arg and env.is_c_class_scope:
747 ## type = Builtin.type_type
748 else:
749 type = py_object_type
750 else:
751 if self.module_path:
752 scope = env.find_imported_module(self.module_path, self.pos)
753 else:
754 scope = env
755 if scope:
756 if scope.is_c_class_scope:
757 scope = scope.global_scope()
758 entry = scope.lookup(self.name)
759 if entry and entry.is_type:
760 type = entry.type
761 elif could_be_name:
762 if self.is_self_arg and env.is_c_class_scope:
763 type = env.parent_type
764 ## elif self.is_type_arg and env.is_c_class_scope:
765 ## type = Builtin.type_type
766 else:
767 type = py_object_type
768 self.arg_name = self.name
769 else:
770 if self.templates:
771 if not self.name in self.templates:
772 error(self.pos, "'%s' is not a type identifier" % self.name)
773 type = PyrexTypes.TemplatePlaceholderType(self.name)
774 else:
775 error(self.pos, "'%s' is not a type identifier" % self.name)
776 if self.complex:
777 if not type.is_numeric or type.is_complex:
778 error(self.pos, "can only complexify c numeric types")
779 type = PyrexTypes.CComplexType(type)
780 type.create_declaration_utility_code(env)
781 if type:
782 return type
783 else:
784 return PyrexTypes.error_type
786 class CNestedBaseTypeNode(CBaseTypeNode):
787 # For C++ classes that live inside other C++ classes.
789 # name string
790 # base_type CBaseTypeNode
792 child_attrs = ['base_type']
794 def analyse(self, env, could_be_name = None):
795 base_type = self.base_type.analyse(env)
796 if base_type is PyrexTypes.error_type:
797 return PyrexTypes.error_type
798 if not base_type.is_cpp_class:
799 error(self.pos, "'%s' is not a valid type scope" % base_type)
800 return PyrexTypes.error_type
801 type_entry = base_type.scope.lookup_here(self.name)
802 if not type_entry or not type_entry.is_type:
803 error(self.pos, "'%s.%s' is not a type identifier" % (base_type, self.name))
804 return PyrexTypes.error_type
805 return type_entry.type
807 class TemplatedTypeNode(CBaseTypeNode):
808 # After parsing:
809 # positional_args [ExprNode] List of positional arguments
810 # keyword_args DictNode Keyword arguments
811 # base_type_node CBaseTypeNode
813 # After analysis:
814 # type PyrexTypes.BufferType or PyrexTypes.CppClassType ...containing the right options
817 child_attrs = ["base_type_node", "positional_args",
818 "keyword_args", "dtype_node"]
820 dtype_node = None
822 name = None
824 def analyse(self, env, could_be_name = False, base_type = None):
825 if base_type is None:
826 base_type = self.base_type_node.analyse(env)
827 if base_type.is_error: return base_type
829 if base_type.is_cpp_class:
830 # Templated class
831 if self.keyword_args and self.keyword_args.key_value_pairs:
832 error(self.pos, "c++ templates cannot take keyword arguments");
833 self.type = PyrexTypes.error_type
834 else:
835 template_types = []
836 for template_node in self.positional_args:
837 type = template_node.analyse_as_type(env)
838 if type is None:
839 error(template_node.pos, "unknown type in template argument")
840 return error_type
841 template_types.append(type)
842 self.type = base_type.specialize_here(self.pos, template_types)
844 elif base_type.is_pyobject:
845 # Buffer
846 import Buffer
848 options = Buffer.analyse_buffer_options(
849 self.pos,
850 env,
851 self.positional_args,
852 self.keyword_args,
853 base_type.buffer_defaults)
855 if sys.version_info[0] < 3:
856 # Py 2.x enforces byte strings as keyword arguments ...
857 options = dict([ (name.encode('ASCII'), value)
858 for name, value in options.iteritems() ])
860 self.type = PyrexTypes.BufferType(base_type, **options)
862 else:
863 # Array
864 empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
865 if len(self.positional_args) > 1 or self.keyword_args.key_value_pairs:
866 error(self.pos, "invalid array declaration")
867 self.type = PyrexTypes.error_type
868 else:
869 # It would be nice to merge this class with CArrayDeclaratorNode,
870 # but arrays are part of the declaration, not the type...
871 if not self.positional_args:
872 dimension = None
873 else:
874 dimension = self.positional_args[0]
875 self.array_declarator = CArrayDeclaratorNode(self.pos,
876 base = empty_declarator,
877 dimension = dimension)
878 self.type = self.array_declarator.analyse(base_type, env)[1]
880 return self.type
882 class CComplexBaseTypeNode(CBaseTypeNode):
883 # base_type CBaseTypeNode
884 # declarator CDeclaratorNode
886 child_attrs = ["base_type", "declarator"]
888 def analyse(self, env, could_be_name = False):
889 base = self.base_type.analyse(env, could_be_name)
890 _, type = self.declarator.analyse(base, env)
891 return type
894 class CVarDefNode(StatNode):
895 # C variable definition or forward/extern function declaration.
896 #
897 # visibility 'private' or 'public' or 'extern'
898 # base_type CBaseTypeNode
899 # declarators [CDeclaratorNode]
900 # in_pxd boolean
901 # api boolean
902 # properties [entry]
904 # decorators [cython.locals(...)] or None
905 # directive_locals { string : NameNode } locals defined by cython.locals(...)
907 child_attrs = ["base_type", "declarators"]
908 properties = ()
910 decorators = None
911 directive_locals = {}
913 def analyse_declarations(self, env, dest_scope = None):
914 if not dest_scope:
915 dest_scope = env
916 self.dest_scope = dest_scope
917 base_type = self.base_type.analyse(env)
919 # If the field is an external typedef, we cannot be sure about the type,
920 # so do conversion ourself rather than rely on the CPython mechanism (through
921 # a property; made in AnalyseDeclarationsTransform).
922 if (dest_scope.is_c_class_scope
923 and self.visibility in ('public', 'readonly')):
924 self.properties = []
925 need_property = True
926 else:
927 need_property = False
928 visibility = self.visibility
930 for declarator in self.declarators:
931 name_declarator, type = declarator.analyse(base_type, env)
932 if not type.is_complete():
933 if not (self.visibility == 'extern' and type.is_array):
934 error(declarator.pos,
935 "Variable type '%s' is incomplete" % type)
936 if self.visibility == 'extern' and type.is_pyobject:
937 error(declarator.pos,
938 "Python object cannot be declared extern")
939 name = name_declarator.name
940 cname = name_declarator.cname
941 if name == '':
942 error(declarator.pos, "Missing name in declaration.")
943 return
944 if type.is_cfunction:
945 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
946 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
947 api = self.api)
948 if entry is not None:
949 entry.directive_locals = self.directive_locals
950 else:
951 if self.directive_locals:
952 s.error("Decorators can only be followed by functions")
953 if self.in_pxd and self.visibility != 'extern':
954 error(self.pos,
955 "Only 'extern' C variable declaration allowed in .pxd file")
956 entry = dest_scope.declare_var(name, type, declarator.pos,
957 cname = cname, visibility = visibility, is_cdef = 1)
958 if need_property:
959 self.properties.append(entry)
962 class CStructOrUnionDefNode(StatNode):
963 # name string
964 # cname string or None
965 # kind "struct" or "union"
966 # typedef_flag boolean
967 # visibility "public" or "private"
968 # in_pxd boolean
969 # attributes [CVarDefNode] or None
970 # entry Entry
971 # packed boolean
973 child_attrs = ["attributes"]
975 def analyse_declarations(self, env):
976 scope = None
977 if self.visibility == 'extern' and self.packed:
978 error(self.pos, "Cannot declare extern struct as 'packed'")
979 if self.attributes is not None:
980 scope = StructOrUnionScope(self.name)
981 self.entry = env.declare_struct_or_union(
982 self.name, self.kind, scope, self.typedef_flag, self.pos,
983 self.cname, visibility = self.visibility, packed = self.packed)
984 if self.attributes is not None:
985 if self.in_pxd and not env.in_cinclude:
986 self.entry.defined_in_pxd = 1
987 for attr in self.attributes:
988 attr.analyse_declarations(env, scope)
989 if self.visibility != 'extern':
990 need_typedef_indirection = False
991 for attr in scope.var_entries:
992 type = attr.type
993 while type.is_array:
994 type = type.base_type
995 if type == self.entry.type:
996 error(attr.pos, "Struct cannot contain itself as a member.")
997 if self.typedef_flag:
998 while type.is_ptr:
999 type = type.base_type
1000 if type == self.entry.type:
1001 need_typedef_indirection = True
1002 if need_typedef_indirection:
1003 # C can't handle typedef structs that refer to themselves.
1004 struct_entry = self.entry
1005 self.entry = env.declare_typedef(
1006 self.name, struct_entry.type, self.pos,
1007 cname = self.cname, visibility='ignore')
1008 struct_entry.type.typedef_flag = False
1009 # FIXME: this might be considered a hack ;-)
1010 struct_entry.cname = struct_entry.type.cname = \
1011 '_' + self.entry.type.typedef_cname
1013 def analyse_expressions(self, env):
1014 pass
1016 def generate_execution_code(self, code):
1017 pass
1020 class CppClassNode(CStructOrUnionDefNode):
1022 # name string
1023 # cname string or None
1024 # visibility "extern"
1025 # in_pxd boolean
1026 # attributes [CVarDefNode] or None
1027 # entry Entry
1028 # base_classes [string]
1029 # templates [string] or None
1031 def analyse_declarations(self, env):
1032 scope = None
1033 if self.attributes is not None:
1034 scope = CppClassScope(self.name, env)
1035 base_class_types = []
1036 for base_class_name in self.base_classes:
1037 base_class_entry = env.lookup(base_class_name)
1038 if base_class_entry is None:
1039 error(self.pos, "'%s' not found" % base_class_name)
1040 elif not base_class_entry.is_type or not base_class_entry.type.is_cpp_class:
1041 error(self.pos, "'%s' is not a cpp class type" % base_class_name)
1042 else:
1043 base_class_types.append(base_class_entry.type)
1044 if self.templates is None:
1045 template_types = None
1046 else:
1047 template_types = [PyrexTypes.TemplatePlaceholderType(template_name) for template_name in self.templates]
1048 self.entry = env.declare_cpp_class(
1049 self.name, scope, self.pos,
1050 self.cname, base_class_types, visibility = self.visibility, templates = template_types)
1051 self.entry.is_cpp_class = 1
1052 if self.attributes is not None:
1053 if self.in_pxd and not env.in_cinclude:
1054 self.entry.defined_in_pxd = 1
1055 for attr in self.attributes:
1056 attr.analyse_declarations(scope)
1058 class CEnumDefNode(StatNode):
1059 # name string or None
1060 # cname string or None
1061 # items [CEnumDefItemNode]
1062 # typedef_flag boolean
1063 # visibility "public" or "private"
1064 # in_pxd boolean
1065 # entry Entry
1067 child_attrs = ["items"]
1069 def analyse_declarations(self, env):
1070 self.entry = env.declare_enum(self.name, self.pos,
1071 cname = self.cname, typedef_flag = self.typedef_flag,
1072 visibility = self.visibility)
1073 if self.items is not None:
1074 if self.in_pxd and not env.in_cinclude:
1075 self.entry.defined_in_pxd = 1
1076 for item in self.items:
1077 item.analyse_declarations(env, self.entry)
1079 def analyse_expressions(self, env):
1080 pass
1082 def generate_execution_code(self, code):
1083 if self.visibility == 'public':
1084 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
1085 for item in self.entry.enum_values:
1086 code.putln("%s = PyInt_FromLong(%s); %s" % (
1087 temp,
1088 item.cname,
1089 code.error_goto_if_null(temp, item.pos)))
1090 code.put_gotref(temp)
1091 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
1092 Naming.module_cname,
1093 item.name,
1094 temp,
1095 code.error_goto(item.pos)))
1096 code.put_decref_clear(temp, PyrexTypes.py_object_type)
1097 code.funcstate.release_temp(temp)
1100 class CEnumDefItemNode(StatNode):
1101 # name string
1102 # cname string or None
1103 # value ExprNode or None
1105 child_attrs = ["value"]
1107 def analyse_declarations(self, env, enum_entry):
1108 if self.value:
1109 self.value.analyse_const_expression(env)
1110 if not self.value.type.is_int:
1111 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
1112 self.value.analyse_const_expression(env)
1113 entry = env.declare_const(self.name, enum_entry.type,
1114 self.value, self.pos, cname = self.cname,
1115 visibility = enum_entry.visibility)
1116 enum_entry.enum_values.append(entry)
1119 class CTypeDefNode(StatNode):
1120 # base_type CBaseTypeNode
1121 # declarator CDeclaratorNode
1122 # visibility "public" or "private"
1123 # in_pxd boolean
1125 child_attrs = ["base_type", "declarator"]
1127 def analyse_declarations(self, env):
1128 base = self.base_type.analyse(env)
1129 name_declarator, type = self.declarator.analyse(base, env)
1130 name = name_declarator.name
1131 cname = name_declarator.cname
1132 entry = env.declare_typedef(name, type, self.pos,
1133 cname = cname, visibility = self.visibility)
1134 if self.in_pxd and not env.in_cinclude:
1135 entry.defined_in_pxd = 1
1137 def analyse_expressions(self, env):
1138 pass
1139 def generate_execution_code(self, code):
1140 pass
1143 class FuncDefNode(StatNode, BlockNode):
1144 # Base class for function definition nodes.
1145 #
1146 # return_type PyrexType
1147 # #filename string C name of filename string const
1148 # entry Symtab.Entry
1149 # needs_closure boolean Whether or not this function has inner functions/classes/yield
1150 # directive_locals { string : NameNode } locals defined by cython.locals(...)
1152 py_func = None
1153 assmt = None
1154 needs_closure = False
1155 modifiers = []
1157 def analyse_default_values(self, env):
1158 genv = env.global_scope()
1159 default_seen = 0
1160 for arg in self.args:
1161 if arg.default:
1162 default_seen = 1
1163 if arg.is_generic:
1164 arg.default.analyse_types(env)
1165 arg.default = arg.default.coerce_to(arg.type, genv)
1166 else:
1167 error(arg.pos,
1168 "This argument cannot have a default value")
1169 arg.default = None
1170 elif arg.kw_only:
1171 default_seen = 1
1172 elif default_seen:
1173 error(arg.pos, "Non-default argument following default argument")
1175 def need_gil_acquisition(self, lenv):
1176 return 0
1178 def create_local_scope(self, env):
1179 genv = env
1180 while genv.is_py_class_scope or genv.is_c_class_scope:
1181 genv = env.outer_scope
1182 if self.needs_closure:
1183 lenv = ClosureScope(name=self.entry.name,
1184 outer_scope = genv,
1185 scope_name=self.entry.cname)
1186 else:
1187 lenv = LocalScope(name=self.entry.name,
1188 outer_scope=genv,
1189 parent_scope=env)
1190 lenv.return_type = self.return_type
1191 type = self.entry.type
1192 if type.is_cfunction:
1193 lenv.nogil = type.nogil and not type.with_gil
1194 self.local_scope = lenv
1195 lenv.directives = env.directives
1196 return lenv
1198 def generate_function_definitions(self, env, code):
1199 import Buffer
1201 lenv = self.local_scope
1202 if lenv.is_closure_scope:
1203 outer_scope_cname = "%s->%s" % (Naming.cur_scope_cname,
1204 Naming.outer_scope_cname)
1205 else:
1206 outer_scope_cname = Naming.outer_scope_cname
1207 lenv.mangle_closure_cnames(outer_scope_cname)
1208 # Generate closure function definitions
1209 self.body.generate_function_definitions(lenv, code)
1210 # generate lambda function definitions
1211 for node in lenv.lambda_defs:
1212 node.generate_function_definitions(lenv, code)
1214 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1215 self.entry.scope.is_c_class_scope)
1216 is_releasebuffer_slot = (self.entry.name == "__releasebuffer__" and
1217 self.entry.scope.is_c_class_scope)
1218 is_buffer_slot = is_getbuffer_slot or is_releasebuffer_slot
1219 if is_buffer_slot:
1220 if 'cython_unused' not in self.modifiers:
1221 self.modifiers = self.modifiers + ['cython_unused']
1223 profile = code.globalstate.directives['profile']
1224 if profile:
1225 if lenv.nogil:
1226 error(self.pos, "Cannot profile nogil function.")
1227 code.globalstate.use_utility_code(profile_utility_code)
1229 # Generate C code for header and body of function
1230 code.enter_cfunc_scope()
1231 code.return_from_error_cleanup_label = code.new_label()
1233 # ----- Top-level constants used by this function
1234 code.mark_pos(self.pos)
1235 self.generate_cached_builtins_decls(lenv, code)
1236 # ----- Function header
1237 code.putln("")
1238 with_pymethdef = self.needs_assignment_synthesis(env, code)
1239 if self.py_func:
1240 self.py_func.generate_function_header(code,
1241 with_pymethdef = with_pymethdef,
1242 proto_only=True)
1243 self.generate_function_header(code,
1244 with_pymethdef = with_pymethdef)
1245 # ----- Local variable declarations
1246 if lenv.is_closure_scope:
1247 code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
1248 code.putln(";")
1249 elif env.is_closure_scope:
1250 code.put(env.scope_class.type.declaration_code(Naming.outer_scope_cname))
1251 code.putln(";")
1252 self.generate_argument_declarations(lenv, code)
1253 for entry in lenv.var_entries:
1254 if not entry.in_closure:
1255 code.put_var_declaration(entry)
1256 init = ""
1257 if not self.return_type.is_void:
1258 if self.return_type.is_pyobject:
1259 init = " = NULL"
1260 code.putln(
1261 "%s%s;" %
1262 (self.return_type.declaration_code(Naming.retval_cname),
1263 init))
1264 tempvardecl_code = code.insertion_point()
1265 self.generate_keyword_list(code)
1266 if profile:
1267 code.put_trace_declarations()
1268 # ----- Extern library function declarations
1269 lenv.generate_library_function_declarations(code)
1270 # ----- GIL acquisition
1271 acquire_gil = self.acquire_gil
1272 if acquire_gil:
1273 env.use_utility_code(force_init_threads_utility_code)
1274 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1275 # ----- set up refnanny
1276 if not lenv.nogil:
1277 code.put_setup_refcount_context(self.entry.name)
1278 # ----- Automatic lead-ins for certain special functions
1279 if is_getbuffer_slot:
1280 self.getbuffer_init(code)
1281 # ----- Create closure scope object
1282 if self.needs_closure:
1283 code.putln("%s = (%s)%s->tp_new(%s, %s, NULL);" % (
1284 Naming.cur_scope_cname,
1285 lenv.scope_class.type.declaration_code(''),
1286 lenv.scope_class.type.typeptr_cname,
1287 lenv.scope_class.type.typeptr_cname,
1288 Naming.empty_tuple))
1289 code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
1290 if is_getbuffer_slot:
1291 self.getbuffer_error_cleanup(code)
1292 if not lenv.nogil:
1293 code.put_finish_refcount_context()
1294 # FIXME: what if the error return value is a Python value?
1295 code.putln("return %s;" % self.error_value())
1296 code.putln("}")
1297 code.put_gotref(Naming.cur_scope_cname)
1298 # Note that it is unsafe to decref the scope at this point.
1299 if env.is_closure_scope:
1300 code.putln("%s = (%s)%s;" % (
1301 outer_scope_cname,
1302 env.scope_class.type.declaration_code(''),
1303 Naming.self_cname))
1304 if self.needs_closure:
1305 # inner closures own a reference to their outer parent
1306 code.put_incref(outer_scope_cname, env.scope_class.type)
1307 code.put_giveref(outer_scope_cname)
1308 # ----- Trace function call
1309 if profile:
1310 # this looks a bit late, but if we don't get here due to a
1311 # fatal error before hand, it's not really worth tracing
1312 code.put_trace_call(self.entry.name, self.pos)
1313 # ----- Fetch arguments
1314 self.generate_argument_parsing_code(env, code)
1315 # If an argument is assigned to in the body, we must
1316 # incref it to properly keep track of refcounts.
1317 for entry in lenv.arg_entries:
1318 if entry.type.is_pyobject:
1319 if entry.assignments and not entry.in_closure:
1320 code.put_var_incref(entry)
1321 # ----- Initialise local variables
1322 for entry in lenv.var_entries:
1323 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1324 code.put_init_var_to_py_none(entry)
1325 # ----- Initialise local buffer auxiliary variables
1326 for entry in lenv.var_entries + lenv.arg_entries:
1327 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1328 code.putln("%s.buf = NULL;" %
1329 entry.buffer_aux.buffer_info_var.cname)
1330 # ----- Check and convert arguments
1331 self.generate_argument_type_tests(code)
1332 # ----- Acquire buffer arguments
1333 for entry in lenv.arg_entries:
1334 if entry.type.is_buffer:
1335 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1337 # -------------------------
1338 # ----- Function body -----
1339 # -------------------------
1340 self.body.generate_execution_code(code)
1342 # ----- Default return value
1343 code.putln("")
1344 if self.return_type.is_pyobject:
1345 #if self.return_type.is_extension_type:
1346 # lhs = "(PyObject *)%s" % Naming.retval_cname
1347 #else:
1348 lhs = Naming.retval_cname
1349 code.put_init_to_py_none(lhs, self.return_type)
1350 else:
1351 val = self.return_type.default_value
1352 if val:
1353 code.putln("%s = %s;" % (Naming.retval_cname, val))
1354 # ----- Error cleanup
1355 if code.error_label in code.labels_used:
1356 code.put_goto(code.return_label)
1357 code.put_label(code.error_label)
1358 for cname, type in code.funcstate.all_managed_temps():
1359 code.put_xdecref(cname, type)
1361 # Clean up buffers -- this calls a Python function
1362 # so need to save and restore error state
1363 buffers_present = len(lenv.buffer_entries) > 0
1364 if buffers_present:
1365 code.globalstate.use_utility_code(restore_exception_utility_code)
1366 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1367 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1368 for entry in lenv.buffer_entries:
1369 Buffer.put_release_buffer_code(code, entry)
1370 #code.putln("%s = 0;" % entry.cname)
1371 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1373 err_val = self.error_value()
1374 exc_check = self.caller_will_check_exceptions()
1375 if err_val is not None or exc_check:
1376 # TODO: Fix exception tracing (though currently unused by cProfile).
1377 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
1378 # code.put_trace_exception()
1379 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1380 else:
1381 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1382 % self.entry.qualified_name, 0)
1383 code.putln(
1384 '__Pyx_WriteUnraisable("%s");' %
1385 self.entry.qualified_name)
1386 env.use_utility_code(unraisable_exception_utility_code)
1387 env.use_utility_code(restore_exception_utility_code)
1388 default_retval = self.return_type.default_value
1389 if err_val is None and default_retval:
1390 err_val = default_retval
1391 if err_val is not None:
1392 code.putln("%s = %s;" % (Naming.retval_cname, err_val))
1394 if is_getbuffer_slot:
1395 self.getbuffer_error_cleanup(code)
1397 # If we are using the non-error cleanup section we should
1398 # jump past it if we have an error. The if-test below determine
1399 # whether this section is used.
1400 if buffers_present or is_getbuffer_slot:
1401 code.put_goto(code.return_from_error_cleanup_label)
1404 # ----- Non-error return cleanup
1405 code.put_label(code.return_label)
1406 for entry in lenv.buffer_entries:
1407 if entry.used:
1408 Buffer.put_release_buffer_code(code, entry)
1409 if is_getbuffer_slot:
1410 self.getbuffer_normal_cleanup(code)
1411 # ----- Return cleanup for both error and no-error return
1412 code.put_label(code.return_from_error_cleanup_label)
1413 if not Options.init_local_none:
1414 for entry in lenv.var_entries:
1415 if lenv.control_flow.get_state((entry.name, 'initialized')) is not True:
1416 entry.xdecref_cleanup = 1
1418 for entry in lenv.var_entries:
1419 if entry.type.is_pyobject:
1420 if entry.used and not entry.in_closure:
1421 code.put_var_decref(entry)
1422 elif entry.in_closure and self.needs_closure:
1423 code.put_giveref(entry.cname)
1424 # Decref any increfed args
1425 for entry in lenv.arg_entries:
1426 if entry.type.is_pyobject:
1427 if entry.in_closure:
1428 code.put_var_giveref(entry)
1429 elif entry.assignments:
1430 code.put_var_decref(entry)
1431 if self.needs_closure:
1432 code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
1434 # ----- Return
1435 # This code is duplicated in ModuleNode.generate_module_init_func
1436 if not lenv.nogil:
1437 default_retval = self.return_type.default_value
1438 err_val = self.error_value()
1439 if err_val is None and default_retval:
1440 err_val = default_retval
1441 if self.return_type.is_pyobject:
1442 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1444 if self.entry.is_special and self.entry.name == "__hash__":
1445 # Returning -1 for __hash__ is supposed to signal an error
1446 # We do as Python instances and coerce -1 into -2.
1447 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
1448 Naming.retval_cname, Naming.retval_cname))
1450 if profile:
1451 if self.return_type.is_pyobject:
1452 code.put_trace_return(Naming.retval_cname)
1453 else:
1454 code.put_trace_return("Py_None")
1455 if not lenv.nogil:
1456 code.put_finish_refcount_context()
1458 if acquire_gil:
1459 code.putln("PyGILState_Release(_save);")
1461 if not self.return_type.is_void:
1462 code.putln("return %s;" % Naming.retval_cname)
1464 code.putln("}")
1465 # ----- Go back and insert temp variable declarations
1466 tempvardecl_code.put_temp_declarations(code.funcstate)
1467 # ----- Python version
1468 code.exit_cfunc_scope()
1469 if self.py_func:
1470 self.py_func.generate_function_definitions(env, code)
1471 self.generate_wrapper_functions(code)
1473 def declare_argument(self, env, arg):
1474 if arg.type.is_void:
1475 error(arg.pos, "Invalid use of 'void'")
1476 elif not arg.type.is_complete() and not arg.type.is_array:
1477 error(arg.pos,
1478 "Argument type '%s' is incomplete" % arg.type)
1479 return env.declare_arg(arg.name, arg.type, arg.pos)
1481 def generate_arg_type_test(self, arg, code):
1482 # Generate type test for one argument.
1483 if arg.type.typeobj_is_available():
1484 code.globalstate.use_utility_code(arg_type_test_utility_code)
1485 typeptr_cname = arg.type.typeptr_cname
1486 arg_code = "((PyObject *)%s)" % arg.entry.cname
1487 code.putln(
1488 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1489 arg_code,
1490 typeptr_cname,
1491 arg.accept_none,
1492 arg.name,
1493 arg.type.is_builtin_type,
1494 code.error_goto(arg.pos)))
1495 else:
1496 error(arg.pos, "Cannot test type of extern C class "
1497 "without type object name specification")
1499 def generate_arg_none_check(self, arg, code):
1500 # Generate None check for one argument.
1501 code.globalstate.use_utility_code(arg_type_test_utility_code)
1502 code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % arg.entry.cname)
1503 code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s''' % (
1504 arg.name,
1505 code.error_goto(arg.pos)))
1506 code.putln('}')
1508 def generate_wrapper_functions(self, code):
1509 pass
1511 def generate_execution_code(self, code):
1512 # Evaluate and store argument default values
1513 for arg in self.args:
1514 default = arg.default
1515 if default:
1516 if not default.is_literal:
1517 default.generate_evaluation_code(code)
1518 default.make_owned_reference(code)
1519 result = default.result_as(arg.type)
1520 code.putln(
1521 "%s = %s;" % (
1522 arg.calculate_default_value_code(code),
1523 result))
1524 if arg.type.is_pyobject:
1525 code.put_giveref(default.result())
1526 default.generate_post_assignment_code(code)
1527 default.free_temps(code)
1528 # For Python class methods, create and store function object
1529 if self.assmt:
1530 self.assmt.generate_execution_code(code)
1532 #
1533 # Special code for the __getbuffer__ function
1534 #
1535 def getbuffer_init(self, code):
1536 info = self.local_scope.arg_entries[1].cname
1537 # Python 3.0 betas have a bug in memoryview which makes it call
1538 # getbuffer with a NULL parameter. For now we work around this;
1539 # the following line should be removed when this bug is fixed.
1540 code.putln("if (%s == NULL) return 0;" % info)
1541 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1542 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1544 def getbuffer_error_cleanup(self, code):
1545 info = self.local_scope.arg_entries[1].cname
1546 code.put_gotref("%s->obj" % info)
1547 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1548 (info, info))
1550 def getbuffer_normal_cleanup(self, code):
1551 info = self.local_scope.arg_entries[1].cname
1552 code.putln("if (%s->obj == Py_None) {" % info)
1553 code.put_gotref("Py_None")
1554 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1555 code.putln("}")
1557 class CFuncDefNode(FuncDefNode):
1558 # C function definition.
1559 #
1560 # modifiers ['inline']
1561 # visibility 'private' or 'public' or 'extern'
1562 # base_type CBaseTypeNode
1563 # declarator CDeclaratorNode
1564 # body StatListNode
1565 # api boolean
1566 # decorators [DecoratorNode] list of decorators
1567 #
1568 # with_gil boolean Acquire GIL around body
1569 # type CFuncType
1570 # py_func wrapper for calling from Python
1571 # overridable whether or not this is a cpdef function
1572 # inline_in_pxd whether this is an inline function in a pxd file
1574 child_attrs = ["base_type", "declarator", "body", "py_func"]
1576 inline_in_pxd = False
1577 decorators = None
1578 directive_locals = {}
1580 def unqualified_name(self):
1581 return self.entry.name
1583 def analyse_declarations(self, env):
1584 self.directive_locals.update(env.directives['locals'])
1585 base_type = self.base_type.analyse(env)
1586 # The 2 here is because we need both function and argument names.
1587 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1588 if not type.is_cfunction:
1589 error(self.pos,
1590 "Suite attached to non-function declaration")
1591 # Remember the actual type according to the function header
1592 # written here, because the type in the symbol table entry
1593 # may be different if we're overriding a C method inherited
1594 # from the base type of an extension type.
1595 self.type = type
1596 type.is_overridable = self.overridable
1597 declarator = self.declarator
1598 while not hasattr(declarator, 'args'):
1599 declarator = declarator.base
1600 self.args = declarator.args
1601 for formal_arg, type_arg in zip(self.args, type.args):
1602 formal_arg.type = type_arg.type
1603 formal_arg.name = type_arg.name
1604 formal_arg.cname = type_arg.cname
1605 name = name_declarator.name
1606 cname = name_declarator.cname
1607 self.entry = env.declare_cfunction(
1608 name, type, self.pos,
1609 cname = cname, visibility = self.visibility,
1610 defining = self.body is not None,
1611 api = self.api, modifiers = self.modifiers)
1612 self.entry.inline_func_in_pxd = self.inline_in_pxd
1613 self.return_type = type.return_type
1615 if self.overridable and not env.is_module_scope:
1616 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1617 # An error will be produced in the cdef function
1618 self.overridable = False
1620 if self.overridable:
1621 import ExprNodes
1622 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1623 self.py_func = DefNode(pos = self.pos,
1624 name = self.entry.name,
1625 args = self.args,
1626 star_arg = None,
1627 starstar_arg = None,
1628 doc = self.doc,
1629 body = py_func_body,
1630 is_wrapper = 1)
1631 self.py_func.is_module_scope = env.is_module_scope
1632 self.py_func.analyse_declarations(env)
1633 self.entry.as_variable = self.py_func.entry
1634 # Reset scope entry the above cfunction
1635 env.entries[name] = self.entry
1636 if not env.is_module_scope or Options.lookup_module_cpdef:
1637 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1638 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1639 self.create_local_scope(env)
1641 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1642 import ExprNodes
1643 args = self.type.args
1644 if omit_optional_args:
1645 args = args[:len(args) - self.type.optional_arg_count]
1646 arg_names = [arg.name for arg in args]
1647 if is_module_scope:
1648 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1649 else:
1650 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1651 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1652 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1653 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)
1654 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1656 def declare_arguments(self, env):
1657 for arg in self.type.args:
1658 if not arg.name:
1659 error(arg.pos, "Missing argument name")
1660 self.declare_argument(env, arg)
1662 def need_gil_acquisition(self, lenv):
1663 return self.type.with_gil
1665 def nogil_check(self, env):
1666 type = self.type
1667 with_gil = type.with_gil
1668 if type.nogil and not with_gil:
1669 if type.return_type.is_pyobject:
1670 error(self.pos,
1671 "Function with Python return type cannot be declared nogil")
1672 for entry in self.local_scope.var_entries:
1673 if entry.type.is_pyobject:
1674 error(self.pos, "Function declared nogil has Python locals or temporaries")
1676 def analyse_expressions(self, env):
1677 self.local_scope.directives = env.directives
1678 if self.py_func is not None:
1679 # this will also analyse the default values
1680 self.py_func.analyse_expressions(env)
1681 else:
1682 self.analyse_default_values(env)
1683 self.acquire_gil = self.need_gil_acquisition(self.local_scope)
1685 def needs_assignment_synthesis(self, env, code=None):
1686 return False
1688 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1689 arg_decls = []
1690 type = self.type
1691 visibility = self.entry.visibility
1692 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1693 arg_decls.append(arg.declaration_code())
1694 if with_dispatch and self.overridable:
1695 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1696 if type.optional_arg_count and with_opt_args:
1697 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1698 if type.has_varargs:
1699 arg_decls.append("...")
1700 if not arg_decls:
1701 arg_decls = ["void"]
1702 if cname is None:
1703 cname = self.entry.func_cname
1704 entity = type.function_header_code(cname, ', '.join(arg_decls))
1705 if visibility == 'public':
1706 dll_linkage = "DL_EXPORT"
1707 else:
1708 dll_linkage = None
1709 header = self.return_type.declaration_code(entity,
1710 dll_linkage = dll_linkage)
1711 if visibility == 'extern':
1712 storage_class = "%s " % Naming.extern_c_macro
1713 elif visibility == 'public':
1714 storage_class = ""
1715 else:
1716 storage_class = "static "
1717 if 'inline' in self.modifiers:
1718 self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
1719 code.putln("%s%s %s {" % (
1720 storage_class,
1721 ' '.join(self.modifiers).upper(), # macro forms
1722 header))
1724 def generate_argument_declarations(self, env, code):
1725 for arg in self.args:
1726 if arg.default:
1727 result = arg.calculate_default_value_code(code)
1728 code.putln('%s = %s;' % (
1729 arg.type.declaration_code(arg.cname), result))
1731 def generate_keyword_list(self, code):
1732 pass
1734 def generate_argument_parsing_code(self, env, code):
1735 i = 0
1736 if self.type.optional_arg_count:
1737 code.putln('if (%s) {' % Naming.optional_args_cname)
1738 for arg in self.args:
1739 if arg.default:
1740 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1741 declarator = arg.declarator
1742 while not hasattr(declarator, 'name'):
1743 declarator = declarator.base
1744 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
1745 i += 1
1746 for _ in range(self.type.optional_arg_count):
1747 code.putln('}')
1748 code.putln('}')
1750 def generate_argument_conversion_code(self, code):
1751 pass
1753 def generate_argument_type_tests(self, code):
1754 # Generate type tests for args whose type in a parent
1755 # class is a supertype of the declared type.
1756 for arg in self.type.args:
1757 if arg.needs_type_test:
1758 self.generate_arg_type_test(arg, code)
1759 elif arg.type.is_pyobject and not arg.accept_none:
1760 self.generate_arg_none_check(arg, code)
1762 def error_value(self):
1763 if self.return_type.is_pyobject:
1764 return "0"
1765 else:
1766 #return None
1767 return self.entry.type.exception_value
1769 def caller_will_check_exceptions(self):
1770 return self.entry.type.exception_check
1772 def generate_wrapper_functions(self, code):
1773 # If the C signature of a function has changed, we need to generate
1774 # wrappers to put in the slots here.
1775 k = 0
1776 entry = self.entry
1777 func_type = entry.type
1778 while entry.prev_entry is not None:
1779 k += 1
1780 entry = entry.prev_entry
1781 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1782 code.putln()
1783 self.generate_function_header(code,
1784 0,
1785 with_dispatch = entry.type.is_overridable,
1786 with_opt_args = entry.type.optional_arg_count,
1787 cname = entry.func_cname)
1788 if not self.return_type.is_void:
1789 code.put('return ')
1790 args = self.type.args
1791 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1792 if entry.type.is_overridable:
1793 arglist.append(Naming.skip_dispatch_cname)
1794 elif func_type.is_overridable:
1795 arglist.append('0')
1796 if entry.type.optional_arg_count:
1797 arglist.append(Naming.optional_args_cname)
1798 elif func_type.optional_arg_count:
1799 arglist.append('NULL')
1800 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1801 code.putln('}')
1804 class PyArgDeclNode(Node):
1805 # Argument which must be a Python object (used
1806 # for * and ** arguments).
1807 #
1808 # name string
1809 # entry Symtab.Entry
1810 # annotation ExprNode or None Py3 argument annotation
1811 child_attrs = []
1813 def generate_function_definitions(self, env, code):
1814 self.entry.generate_function_definitions(env, code)
1816 class DecoratorNode(Node):
1817 # A decorator
1818 #
1819 # decorator NameNode or CallNode or AttributeNode
1820 child_attrs = ['decorator']
1823 class DefNode(FuncDefNode):
1824 # A Python function definition.
1825 #
1826 # name string the Python name of the function
1827 # lambda_name string the internal name of a lambda 'function'
1828 # decorators [DecoratorNode] list of decorators
1829 # args [CArgDeclNode] formal arguments
1830 # star_arg PyArgDeclNode or None * argument
1831 # starstar_arg PyArgDeclNode or None ** argument
1832 # doc EncodedString or None
1833 # body StatListNode
1834 # return_type_annotation
1835 # ExprNode or None the Py3 return type annotation
1836 #
1837 # The following subnode is constructed internally
1838 # when the def statement is inside a Python class definition.
1839 #
1840 # assmt AssignmentNode Function construction/assignment
1842 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1844 lambda_name = None
1845 assmt = None
1846 num_kwonly_args = 0
1847 num_required_kw_args = 0
1848 reqd_kw_flags_cname = "0"
1849 is_wrapper = 0
1850 decorators = None
1851 return_type_annotation = None
1852 entry = None
1853 acquire_gil = 0
1854 self_in_stararg = 0
1856 def __init__(self, pos, **kwds):
1857 FuncDefNode.__init__(self, pos, **kwds)
1858 k = rk = r = 0
1859 for arg in self.args:
1860 if arg.kw_only:
1861 k += 1
1862 if not arg.default:
1863 rk += 1
1864 if not arg.default:
1865 r += 1
1866 self.num_kwonly_args = k
1867 self.num_required_kw_args = rk
1868 self.num_required_args = r
1870 def as_cfunction(self, cfunc=None, scope=None):
1871 if self.star_arg:
1872 error(self.star_arg.pos, "cdef function cannot have star argument")
1873 if self.starstar_arg:
1874 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1875 if cfunc is None:
1876 cfunc_args = []
1877 for formal_arg in self.args:
1878 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1879 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1880 cname = None,
1881 type = py_object_type,
1882 pos = formal_arg.pos))
1883 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1884 args = cfunc_args,
1885 has_varargs = False,
1886 exception_value = None,
1887 exception_check = False,
1888 nogil = False,
1889 with_gil = False,
1890 is_overridable = True)
1891 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1892 else:
1893 cfunc_type = cfunc.type
1894 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1895 error(self.pos, "wrong number of arguments")
1896 error(cfunc.pos, "previous declaration here")
1897 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1898 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1899 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1900 formal_arg.type = type_arg.type
1901 formal_arg.name_declarator = name_declarator
1902 import ExprNodes
1903 if cfunc_type.exception_value is None:
1904 exception_value = None
1905 else:
1906 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1907 declarator = CFuncDeclaratorNode(self.pos,
1908 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1909 args = self.args,
1910 has_varargs = False,
1911 exception_check = cfunc_type.exception_check,
1912 exception_value = exception_value,
1913 with_gil = cfunc_type.with_gil,
1914 nogil = cfunc_type.nogil)
1915 return CFuncDefNode(self.pos,
1916 modifiers = [],
1917 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1918 declarator = declarator,
1919 body = self.body,
1920 doc = self.doc,
1921 overridable = cfunc_type.is_overridable,
1922 type = cfunc_type,
1923 with_gil = cfunc_type.with_gil,
1924 nogil = cfunc_type.nogil,
1925 visibility = 'private',
1926 api = False,
1927 directive_locals = getattr(cfunc, 'directive_locals', {}))
1929 def analyse_declarations(self, env):
1930 self.is_classmethod = self.is_staticmethod = False
1931 if self.decorators:
1932 for decorator in self.decorators:
1933 func = decorator.decorator
1934 if func.is_name:
1935 self.is_classmethod |= func.name == 'classmethod'
1936 self.is_staticmethod |= func.name == 'staticmethod'
1938 if self.is_classmethod and env.lookup_here('classmethod'):
1939 # classmethod() was overridden - not much we can do here ...
1940 self.is_classmethod = False
1941 if self.is_staticmethod and env.lookup_here('staticmethod'):
1942 # staticmethod() was overridden - not much we can do here ...
1943 self.is_staticmethod = False
1945 self.analyse_argument_types(env)
1946 if self.name == '<lambda>':
1947 self.declare_lambda_function(env)
1948 else:
1949 self.declare_pyfunction(env)
1950 self.analyse_signature(env)
1951 self.return_type = self.entry.signature.return_type()
1952 self.create_local_scope(env)
1954 def analyse_argument_types(self, env):
1955 directive_locals = self.directive_locals = env.directives['locals']
1956 allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
1957 for arg in self.args:
1958 if hasattr(arg, 'name'):
1959 type = arg.type
1960 name_declarator = None
1961 else:
1962 base_type = arg.base_type.analyse(env)
1963 name_declarator, type = \
1964 arg.declarator.analyse(base_type, env)
1965 arg.name = name_declarator.name
1966 if arg.name in directive_locals:
1967 type_node = directive_locals[arg.name]
1968 other_type = type_node.analyse_as_type(env)
1969 if other_type is None:
1970 error(type_node.pos, "Not a type")
1971 elif (type is not PyrexTypes.py_object_type
1972 and not type.same_as(other_type)):
1973 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1974 error(type_node.pos, "Previous declaration here")
1975 else:
1976 type = other_type
1977 if name_declarator and name_declarator.cname:
1978 error(self.pos,
1979 "Python function argument cannot have C name specification")
1980 arg.type = type.as_argument_type()
1981 arg.hdr_type = None
1982 arg.needs_conversion = 0
1983 arg.needs_type_test = 0
1984 arg.is_generic = 1
1985 if arg.type.is_pyobject:
1986 if arg.or_none:
1987 arg.accept_none = True
1988 elif arg.not_none:
1989 arg.accept_none = False
1990 elif arg.type.is_extension_type or arg.type.is_builtin_type:
1991 if arg.default and arg.default.constant_result is None:
1992 # special case: def func(MyType obj = None)
1993 arg.accept_none = True
1994 else:
1995 # default depends on compiler directive
1996 arg.accept_none = allow_none_for_extension_args
1997 else:
1998 # probably just a plain 'object'
1999 arg.accept_none = True
2000 else:
2001 arg.accept_none = True # won't be used, but must be there
2002 if arg.not_none:
2003 error(arg.pos, "Only Python type arguments can have 'not None'")
2004 if arg.or_none:
2005 error(arg.pos, "Only Python type arguments can have 'or None'")
2007 def analyse_signature(self, env):
2008 if self.entry.is_special:
2009 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
2010 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
2011 # Use the simpler calling signature for zero- and one-argument functions.
2012 if self.entry.signature is TypeSlots.pyfunction_signature:
2013 if len(self.args) == 0:
2014 self.entry.signature = TypeSlots.pyfunction_noargs
2015 elif len(self.args) == 1:
2016 if self.args[0].default is None and not self.args[0].kw_only:
2017 self.entry.signature = TypeSlots.pyfunction_onearg
2018 elif self.entry.signature is TypeSlots.pymethod_signature:
2019 if len(self.args) == 1:
2020 self.entry.signature = TypeSlots.unaryfunc
2021 elif len(self.args) == 2:
2022 if self.args[1].default is None and not self.args[1].kw_only:
2023 self.entry.signature = TypeSlots.ibinaryfunc
2025 sig = self.entry.signature
2026 nfixed = sig.num_fixed_args()
2027 if sig is TypeSlots.pymethod_signature and nfixed == 1 \
2028 and len(self.args) == 0 and self.star_arg:
2029 # this is the only case where a diverging number of
2030 # arguments is not an error - when we have no explicit
2031 # 'self' parameter as in method(*args)
2032 sig = self.entry.signature = TypeSlots.pyfunction_signature # self is not 'really' used
2033 self.self_in_stararg = 1
2034 nfixed = 0
2036 for i in range(min(nfixed, len(self.args))):
2037 arg = self.args[i]
2038 arg.is_generic = 0
2039 if sig.is_self_arg(i) and not self.is_staticmethod:
2040 if self.is_classmethod:
2041 arg.is_type_arg = 1
2042 arg.hdr_type = arg.type = Builtin.type_type
2043 else:
2044 arg.is_self_arg = 1
2045 arg.hdr_type = arg.type = env.parent_type
2046 arg.needs_conversion = 0
2047 else:
2048 arg.hdr_type = sig.fixed_arg_type(i)
2049 if not arg.type.same_as(arg.hdr_type):
2050 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
2051 arg.needs_type_test = 1
2052 else:
2053 arg.needs_conversion = 1
2054 if arg.needs_conversion:
2055 arg.hdr_cname = Naming.arg_prefix + arg.name
2056 else:
2057 arg.hdr_cname = Naming.var_prefix + arg.name
2059 if nfixed > len(self.args):
2060 self.bad_signature()
2061 return
2062 elif nfixed < len(self.args):
2063 if not sig.has_generic_args:
2064 self.bad_signature()
2065 for arg in self.args:
2066 if arg.is_generic and \
2067 (arg.type.is_extension_type or arg.type.is_builtin_type):
2068 arg.needs_type_test = 1
2070 def bad_signature(self):
2071 sig = self.entry.signature
2072 expected_str = "%d" % sig.num_fixed_args()
2073 if sig.has_generic_args:
2074 expected_str = expected_str + " or more"
2075 name = self.name
2076 if name.startswith("__") and name.endswith("__"):
2077 desc = "Special method"
2078 else:
2079 desc = "Method"
2080 error(self.pos,
2081 "%s %s has wrong number of arguments "
2082 "(%d declared, %s expected)" % (
2083 desc, self.name, len(self.args), expected_str))
2085 def signature_has_nongeneric_args(self):
2086 argcount = len(self.args)
2087 if argcount == 0 or (
2088 argcount == 1 and (self.args[0].is_self_arg or
2089 self.args[0].is_type_arg)):
2090 return 0
2091 return 1
2093 def signature_has_generic_args(self):
2094 return self.entry.signature.has_generic_args
2096 def declare_pyfunction(self, env):
2097 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
2098 name = self.name
2099 entry = env.lookup_here(name)
2100 if entry and entry.type.is_cfunction and not self.is_wrapper:
2101 warning(self.pos, "Overriding cdef method with def method.", 5)
2102 entry = env.declare_pyfunction(name, self.pos)
2103 self.entry = entry
2104 prefix = env.scope_prefix
2105 entry.func_cname = \
2106 Naming.pyfunc_prefix + prefix + name
2107 entry.pymethdef_cname = \
2108 Naming.pymethdef_prefix + prefix + name
2109 if Options.docstrings:
2110 entry.doc = embed_position(self.pos, self.doc)
2111 entry.doc_cname = \
2112 Naming.funcdoc_prefix + prefix + name
2113 if entry.is_special:
2114 entry.wrapperbase_cname = Naming.wrapperbase_prefix + prefix + name
2115 else:
2116 entry.doc = None
2118 def declare_lambda_function(self, env):
2119 name = self.name
2120 prefix = env.scope_prefix
2121 func_cname = \
2122 Naming.lambda_func_prefix + u'funcdef' + prefix + self.lambda_name
2123 entry = env.declare_lambda_function(func_cname, self.pos)
2124 entry.pymethdef_cname = \
2125 Naming.lambda_func_prefix + u'methdef' + prefix + self.lambda_name
2126 entry.qualified_name = env.qualify_name(self.lambda_name)
2127 entry.doc = None
2128 self.entry = entry
2130 def declare_arguments(self, env):
2131 for arg in self.args:
2132 if not arg.name:
2133 error(arg.pos, "Missing argument name")
2134 else:
2135 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
2136 env.control_flow.set_state((), (arg.name, 'initialized'), True)
2137 if arg.needs_conversion:
2138 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
2139 if arg.type.is_pyobject:
2140 arg.entry.init = "0"
2141 arg.entry.init_to_none = 0
2142 else:
2143 arg.entry = self.declare_argument(env, arg)
2144 arg.entry.used = 1
2145 arg.entry.is_self_arg = arg.is_self_arg
2146 if arg.hdr_type:
2147 if arg.is_self_arg or arg.is_type_arg or \
2148 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
2149 arg.entry.is_declared_generic = 1
2150 self.declare_python_arg(env, self.star_arg)
2151 self.declare_python_arg(env, self.starstar_arg)
2153 def declare_python_arg(self, env, arg):
2154 if arg:
2155 if env.directives['infer_types'] != False:
2156 type = PyrexTypes.unspecified_type
2157 else:
2158 type = py_object_type
2159 entry = env.declare_var(arg.name, type, arg.pos)
2160 entry.used = 1
2161 entry.init = "0"
2162 entry.init_to_none = 0
2163 entry.xdecref_cleanup = 1
2164 arg.entry = entry
2165 env.control_flow.set_state((), (arg.name, 'initialized'), True)
2167 def analyse_expressions(self, env):
2168 self.local_scope.directives = env.directives
2169 self.analyse_default_values(env)
2170 if self.needs_assignment_synthesis(env):
2171 # Shouldn't we be doing this at the module level too?
2172 self.synthesize_assignment_node(env)
2174 def needs_assignment_synthesis(self, env, code=None):
2175 # Should enable for module level as well, that will require more testing...
2176 if env.is_module_scope:
2177 if code is None:
2178 return env.directives['binding']
2179 else:
2180 return code.globalstate.directives['binding']
2181 return env.is_py_class_scope or env.is_closure_scope
2183 def synthesize_assignment_node(self, env):
2184 import ExprNodes
2185 if env.is_py_class_scope:
2186 rhs = ExprNodes.UnboundMethodNode(self.pos,
2187 function = ExprNodes.PyCFunctionNode(self.pos,
2188 pymethdef_cname = self.entry.pymethdef_cname))
2189 elif env.is_closure_scope:
2190 rhs = ExprNodes.InnerFunctionNode(
2191 self.pos, pymethdef_cname = self.entry.pymethdef_cname)
2192 else:
2193 rhs = ExprNodes.PyCFunctionNode(
2194 self.pos, pymethdef_cname = self.entry.pymethdef_cname, binding = env.directives['binding'])
2195 self.assmt = SingleAssignmentNode(self.pos,
2196 lhs = ExprNodes.NameNode(self.pos, name = self.name),
2197 rhs = rhs)
2198 self.assmt.analyse_declarations(env)
2199 self.assmt.analyse_expressions(env)
2201 def generate_function_header(self, code, with_pymethdef, proto_only=0):
2202 arg_code_list = []
2203 sig = self.entry.signature
2204 if sig.has_dummy_arg or self.self_in_stararg:
2205 arg_code_list.append(
2206 "PyObject *%s" % Naming.self_cname)
2207 for arg in self.args:
2208 if not arg.is_generic:
2209 if arg.is_self_arg or arg.is_type_arg:
2210 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
2211 else:
2212 arg_code_list.append(
2213 arg.hdr_type.declaration_code(arg.hdr_cname))
2214 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
2215 arg_code_list.append("CYTHON_UNUSED PyObject *unused")
2216 if sig.has_generic_args:
2217 arg_code_list.append(
2218 "PyObject *%s, PyObject *%s"
2219 % (Naming.args_cname, Naming.kwds_cname))
2220 arg_code = ", ".join(arg_code_list)
2221 dc = self.return_type.declaration_code(self.entry.func_cname)
2222 mf = " ".join(self.modifiers).upper()
2223 if mf: mf += " "
2224 header = "static %s%s(%s)" % (mf, dc, arg_code)
2225 code.putln("%s; /*proto*/" % header)
2226 if proto_only:
2227 return
2228 if (Options.docstrings and self.entry.doc and
2229 not self.entry.scope.is_property_scope):
2230 docstr = self.entry.doc
2231 if docstr.is_unicode:
2232 docstr = docstr.utf8encode()
2233 code.putln(
2234 'static char %s[] = "%s";' % (
2235 self.entry.doc_cname,
2236 split_string_literal(escape_byte_string(docstr))))
2237 if self.entry.is_special:
2238 code.putln(
2239 "struct wrapperbase %s;" % self.entry.wrapperbase_cname)
2240 if with_pymethdef:
2241 code.put(
2242 "static PyMethodDef %s = " %
2243 self.entry.pymethdef_cname)
2244 code.put_pymethoddef(self.entry, ";", allow_skip=False)
2245 code.putln("%s {" % header)
2247 def generate_argument_declarations(self, env, code):
2248 for arg in self.args:
2249 if arg.is_generic: # or arg.needs_conversion:
2250 if arg.needs_conversion:
2251 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
2252 elif not arg.entry.in_closure:
2253 code.put_var_declaration(arg.entry)
2255 def generate_keyword_list(self, code):
2256 if self.signature_has_generic_args() and \
2257 self.signature_has_nongeneric_args():
2258 code.put(
2259 "static PyObject **%s[] = {" %
2260 Naming.pykwdlist_cname)
2261 for arg in self.args:
2262 if arg.is_generic:
2263 pystring_cname = code.intern_identifier(arg.name)
2264 code.put('&%s,' % pystring_cname)
2265 code.putln("0};")
2267 def generate_argument_parsing_code(self, env, code):
2268 # Generate PyArg_ParseTuple call for generic
2269 # arguments, if any.
2270 if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
2271 # get rid of unused argument warning
2272 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
2274 old_error_label = code.new_error_label()
2275 our_error_label = code.error_label
2276 end_label = code.new_label("argument_unpacking_done")
2278 has_kwonly_args = self.num_kwonly_args > 0
2279 has_star_or_kw_args = self.star_arg is not None \
2280 or self.starstar_arg is not None or has_kwonly_args
2282 for arg in self.args:
2283 if not arg.type.is_pyobject:
2284 done = arg.type.create_from_py_utility_code(env)
2285 if not done: pass # will fail later
2287 if not self.signature_has_generic_args():
2288 if has_star_or_kw_args:
2289 error(self.pos, "This method cannot have * or keyword arguments")
2290 self.generate_argument_conversion_code(code)
2292 elif not self.signature_has_nongeneric_args():
2293 # func(*args) or func(**kw) or func(*args, **kw)
2294 self.generate_stararg_copy_code(code)
2296 else:
2297 positional_args = []
2298 kw_only_args = []
2299 for arg in self.args:
2300 arg_entry = arg.entry
2301 if arg.is_generic:
2302 if arg.default:
2303 if not arg.is_self_arg and not arg.is_type_arg:
2304 if arg.kw_only:
2305 kw_only_args.append(arg)
2306 else:
2307 positional_args.append(arg)
2308 elif arg.kw_only:
2309 kw_only_args.append(arg)
2310 elif not arg.is_self_arg and not arg.is_type_arg:
2311 positional_args.append(arg)
2313 self.generate_tuple_and_keyword_parsing_code(
2314 positional_args, kw_only_args, end_label, code)
2316 code.error_label = old_error_label
2317 if code.label_used(our_error_label):
2318 if not code.label_used(end_label):
2319 code.put_goto(end_label)
2320 code.put_label(our_error_label)
2321 if has_star_or_kw_args:
2322 self.generate_arg_decref(self.star_arg, code)
2323 if self.starstar_arg:
2324 if self.starstar_arg.entry.xdecref_cleanup:
2325 code.put_var_xdecref(self.starstar_arg.entry)
2326 else:
2327 code.put_var_decref(self.starstar_arg.entry)
2328 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
2329 # The arguments are put into the closure one after the
2330 # other, so when type errors are found, all references in
2331 # the closure instance must be properly ref-counted to
2332 # facilitate generic closure instance deallocation. In
2333 # the case of an argument type error, it's best to just
2334 # DECREF+clear the already handled references, as this
2335 # frees their references as early as possible.
2336 for arg in self.args:
2337 if arg.type.is_pyobject and arg.entry.in_closure:
2338 code.put_var_xdecref_clear(arg.entry)
2339 if self.needs_closure:
2340 code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
2341 code.put_finish_refcount_context()
2342 code.putln("return %s;" % self.error_value())
2343 if code.label_used(end_label):
2344 code.put_label(end_label)
2346 def generate_arg_assignment(self, arg, item, code):
2347 if arg.type.is_pyobject:
2348 if arg.is_generic:
2349 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
2350 entry = arg.entry
2351 code.putln("%s = %s;" % (entry.cname, item))
2352 if entry.in_closure:
2353 code.put_var_incref(entry)
2354 else:
2355 func = arg.type.from_py_function
2356 if func:
2357 code.putln("%s = %s(%s); %s" % (
2358 arg.entry.cname,
2359 func,
2360 item,
2361 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
2362 else:
2363 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
2365 def generate_arg_xdecref(self, arg, code):
2366 if arg:
2367 code.put_var_xdecref(arg.entry)
2369 def generate_arg_decref(self, arg, code):
2370 if arg:
2371 code.put_var_decref(arg.entry)
2373 def generate_stararg_copy_code(self, code):
2374 if not self.star_arg:
2375 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2376 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
2377 Naming.args_cname)
2378 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
2379 self.name, Naming.args_cname, self.error_value()))
2380 code.putln("}")
2382 code.globalstate.use_utility_code(keyword_string_check_utility_code)
2384 if self.starstar_arg:
2385 if self.star_arg:
2386 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
2387 else:
2388 kwarg_check = "%s" % Naming.kwds_cname
2389 else:
2390 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
2391 Naming.kwds_cname, Naming.kwds_cname)
2392 code.putln(
2393 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
2394 kwarg_check, Naming.kwds_cname, self.name,
2395 bool(self.starstar_arg), self.error_value()))
2397 if self.starstar_arg:
2398 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
2399 self.starstar_arg.entry.cname,
2400 Naming.kwds_cname,
2401 Naming.kwds_cname))
2402 code.putln("if (unlikely(!%s)) return %s;" % (
2403 self.starstar_arg.entry.cname, self.error_value()))
2404 self.starstar_arg.entry.xdecref_cleanup = 0
2405 code.put_gotref(self.starstar_arg.entry.cname)
2407 if self.self_in_stararg:
2408 # need to create a new tuple with 'self' inserted as first item
2409 code.put("%s = PyTuple_New(PyTuple_GET_SIZE(%s)+1); if (unlikely(!%s)) " % (
2410 self.star_arg.entry.cname,
2411 Naming.args_cname,
2412 self.star_arg.entry.cname))
2413 if self.starstar_arg:
2414 code.putln("{")
2415 code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
2416 code.putln("return %s;" % self.error_value())
2417 code.putln("}")
2418 else:
2419 code.putln("return %s;" % self.error_value())
2420 code.put_gotref(self.star_arg.entry.cname)
2421 code.put_incref(Naming.self_cname, py_object_type)
2422 code.put_giveref(Naming.self_cname)
2423 code.putln("PyTuple_SET_ITEM(%s, 0, %s);" % (
2424 self.star_arg.entry.cname, Naming.self_cname))
2425 temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False)
2426 code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
2427 temp, temp, Naming.args_cname, temp))
2428 code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
2429 Naming.args_cname, temp))
2430 code.put_incref("item", py_object_type)
2431 code.put_giveref("item")
2432 code.putln("PyTuple_SET_ITEM(%s, %s+1, item);" % (
2433 self.star_arg.entry.cname, temp))
2434 code.putln("}")
2435 code.funcstate.release_temp(temp)
2436 self.star_arg.entry.xdecref_cleanup = 0
2437 elif self.star_arg:
2438 code.put_incref(Naming.args_cname, py_object_type)
2439 code.putln("%s = %s;" % (
2440 self.star_arg.entry.cname,
2441 Naming.args_cname))
2442 self.star_arg.entry.xdecref_cleanup = 0
2444 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2445 kw_only_args, success_label, code):
2446 argtuple_error_label = code.new_label("argtuple_error")
2448 min_positional_args = self.num_required_args - self.num_required_kw_args
2449 if len(self.args) > 0 and (self.args[0].is_self_arg or self.args[0].is_type_arg):
2450 min_positional_args -= 1
2451 max_positional_args = len(positional_args)
2452 has_fixed_positional_count = not self.star_arg and \
2453 min_positional_args == max_positional_args
2455 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2456 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2457 if self.num_required_kw_args:
2458 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2460 if self.starstar_arg or self.star_arg:
2461 self.generate_stararg_init_code(max_positional_args, code)
2463 # --- optimised code when we receive keyword arguments
2464 if self.num_required_kw_args:
2465 likely_hint = "likely"
2466 else:
2467 likely_hint = "unlikely"
2468 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2469 self.generate_keyword_unpacking_code(
2470 min_positional_args, max_positional_args,
2471 has_fixed_positional_count,
2472 positional_args, kw_only_args, argtuple_error_label, code)
2474 # --- optimised code when we do not receive any keyword arguments
2475 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2476 # Python raises arg tuple related errors first, so we must
2477 # check the length here
2478 if min_positional_args == max_positional_args and not self.star_arg:
2479 compare = '!='
2480 else:
2481 compare = '<'
2482 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2483 Naming.args_cname, compare, min_positional_args))
2484 code.put_goto(argtuple_error_label)
2486 if self.num_required_kw_args:
2487 # pure error case: keywords required but not passed
2488 if max_positional_args > min_positional_args and not self.star_arg:
2489 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2490 Naming.args_cname, max_positional_args))
2491 code.put_goto(argtuple_error_label)
2492 code.putln('} else {')
2493 for i, arg in enumerate(kw_only_args):
2494 if not arg.default:
2495 pystring_cname = code.intern_identifier(arg.name)
2496 # required keyword-only argument missing
2497 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2498 self.name,
2499 pystring_cname))
2500 code.putln(code.error_goto(self.pos))
2501 break
2503 elif min_positional_args == max_positional_args:
2504 # parse the exact number of positional arguments from the
2505 # args tuple
2506 code.putln('} else {')
2507 for i, arg in enumerate(positional_args):
2508 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2509 self.generate_arg_assignment(arg, item, code)
2510 self.generate_arg_default_assignments(code)
2512 else:
2513 # parse the positional arguments from the variable length
2514 # args tuple
2515 code.putln('} else {')
2516 self.generate_arg_default_assignments(code)
2517 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2518 if self.star_arg:
2519 code.putln('default:')
2520 reversed_args = list(enumerate(positional_args))[::-1]
2521 for i, arg in reversed_args:
2522 if i >= min_positional_args-1:
2523 if min_positional_args > 1:
2524 code.putln('case %2d:' % (i+1)) # pure code beautification
2525 else:
2526 code.put('case %2d: ' % (i+1))
2527 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2528 self.generate_arg_assignment(arg, item, code)
2529 if min_positional_args == 0:
2530 code.put('case 0: ')
2531 code.putln('break;')
2532 if self.star_arg:
2533 if min_positional_args:
2534 for i in range(min_positional_args-1, -1, -1):
2535 code.putln('case %2d:' % i)
2536 code.put_goto(argtuple_error_label)
2537 else:
2538 code.put('default: ')
2539 code.put_goto(argtuple_error_label)
2540 code.putln('}')
2542 code.putln('}')
2544 if code.label_used(argtuple_error_label):
2545 code.put_goto(success_label)
2546 code.put_label(argtuple_error_label)
2547 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2548 self.name, has_fixed_positional_count,
2549 min_positional_args, max_positional_args,
2550 Naming.args_cname))
2551 code.putln(code.error_goto(self.pos))
2553 def generate_arg_default_assignments(self, code):
2554 for arg in self.args:
2555 if arg.is_generic and arg.default:
2556 code.putln(
2557 "%s = %s;" % (
2558 arg.entry.cname,
2559 arg.calculate_default_value_code(code)))
2561 def generate_stararg_init_code(self, max_positional_args, code):
2562 if self.starstar_arg:
2563 self.starstar_arg.entry.xdecref_cleanup = 0
2564 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2565 self.starstar_arg.entry.cname,
2566 self.starstar_arg.entry.cname,
2567 self.error_value()))
2568 code.put_gotref(self.starstar_arg.entry.cname)
2569 if self.star_arg:
2570 self.star_arg.entry.xdecref_cleanup = 0
2571 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2572 Naming.args_cname,
2573 max_positional_args))
2574 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2575 self.star_arg.entry.cname, Naming.args_cname,
2576 max_positional_args, Naming.args_cname))
2577 code.put_gotref(self.star_arg.entry.cname)
2578 if self.starstar_arg:
2579 code.putln("")
2580 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2581 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2582 code.putln('return %s;' % self.error_value())
2583 code.putln('}')
2584 else:
2585 code.putln("if (unlikely(!%s)) return %s;" % (
2586 self.star_arg.entry.cname, self.error_value()))
2587 code.putln('} else {')
2588 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2589 code.put_incref(Naming.empty_tuple, py_object_type)
2590 code.putln('}')
2592 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2593 has_fixed_positional_count, positional_args,
2594 kw_only_args, argtuple_error_label, code):
2595 all_args = tuple(positional_args) + tuple(kw_only_args)
2596 max_args = len(all_args)
2598 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2599 Naming.kwds_cname)
2600 # the 'values' array collects borrowed references to arguments
2601 # before doing any type coercion etc.
2602 code.putln("PyObject* values[%d] = {%s};" % (
2603 max_args, ','.join('0'*max_args)))
2605 # assign borrowed Python default values to the values array,
2606 # so that they can be overwritten by received arguments below
2607 for i, arg in enumerate(all_args):
2608 if arg.default and arg.type.is_pyobject:
2609 default_value = arg.calculate_default_value_code(code)
2610 code.putln('values[%d] = %s;' % (i, arg.type.as_pyobject(default_value)))
2612 # parse the args tuple and check that it's not too long
2613 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2614 if self.star_arg:
2615 code.putln('default:')
2616 for i in range(max_positional_args-1, -1, -1):
2617 code.put('case %2d: ' % (i+1))
2618 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2619 i, Naming.args_cname, i))
2620 code.putln('case 0: break;')
2621 if not self.star_arg:
2622 code.put('default: ') # more arguments than allowed
2623 code.put_goto(argtuple_error_label)
2624 code.putln('}')
2626 # now fill up the positional/required arguments with values
2627 # from the kw dict
2628 if self.num_required_args or max_positional_args > 0:
2629 last_required_arg = -1
2630 for i, arg in enumerate(all_args):
2631 if not arg.default:
2632 last_required_arg = i
2633 if last_required_arg < max_positional_args:
2634 last_required_arg = max_positional_args-1
2635 num_required_args = self.num_required_args
2636 if max_positional_args > 0:
2637 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2638 for i, arg in enumerate(all_args[:last_required_arg+1]):
2639 if max_positional_args > 0 and i <= max_positional_args:
2640 if self.star_arg and i == max_positional_args:
2641 code.putln('default:')
2642 else:
2643 code.putln('case %2d:' % i)
2644 pystring_cname = code.intern_identifier(arg.name)
2645 if arg.default:
2646 if arg.kw_only:
2647 # handled separately below
2648 continue
2649 code.putln('if (kw_args > 0) {')
2650 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2651 Naming.kwds_cname, pystring_cname))
2652 code.putln('if (value) { values[%d] = value; kw_args--; }' % i)
2653 code.putln('}')
2654 else:
2655 num_required_args -= 1
2656 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2657 i, Naming.kwds_cname, pystring_cname))
2658 code.putln('if (likely(values[%d])) kw_args--;' % i);
2659 if i < min_positional_args:
2660 if i == 0:
2661 # special case: we know arg 0 is missing
2662 code.put('else ')
2663 code.put_goto(argtuple_error_label)
2664 else:
2665 # print the correct number of values (args or
2666 # kwargs) that were passed into positional
2667 # arguments up to this point
2668 code.putln('else {')
2669 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2670 self.name, has_fixed_positional_count,
2671 min_positional_args, max_positional_args, i))
2672 code.putln(code.error_goto(self.pos))
2673 code.putln('}')
2674 elif arg.kw_only:
2675 code.putln('else {')
2676 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2677 self.name, pystring_cname))
2678 code.putln(code.error_goto(self.pos))
2679 code.putln('}')
2680 if max_positional_args > 0:
2681 code.putln('}')
2683 if kw_only_args and not self.starstar_arg:
2684 # unpack optional keyword-only arguments
2685 # checking for interned strings in a dict is faster than iterating
2686 # but it's too likely that we must iterate if we expect **kwargs
2687 optional_args = []
2688 for i, arg in enumerate(all_args[max_positional_args:]):
2689 if not arg.kw_only or not arg.default:
2690 continue
2691 optional_args.append((i+max_positional_args, arg))
2692 if optional_args:
2693 # this mimics an unrolled loop so that we can "break" out of it
2694 code.putln('while (kw_args > 0) {')
2695 code.putln('PyObject* value;')
2696 for i, arg in optional_args:
2697 pystring_cname = code.intern_identifier(arg.name)
2698 code.putln(
2699 'value = PyDict_GetItem(%s, %s);' % (
2700 Naming.kwds_cname, pystring_cname))
2701 code.putln(
2702 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2703 code.putln('break;')
2704 code.putln('}')
2706 code.putln('if (unlikely(kw_args > 0)) {')
2707 # non-positional/-required kw args left in dict: default args,
2708 # kw-only args, **kwargs or error
2709 #
2710 # This is sort of a catch-all: except for checking required
2711 # arguments, this will always do the right thing for unpacking
2712 # keyword arguments, so that we can concentrate on optimising
2713 # common cases above.
2714 if max_positional_args == 0:
2715 pos_arg_count = "0"
2716 elif self.star_arg:
2717 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2718 Naming.args_cname, max_positional_args,
2719 Naming.args_cname, max_positional_args))
2720 pos_arg_count = "used_pos_args"
2721 else:
2722 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2723 code.globalstate.use_utility_code(parse_keywords_utility_code)
2724 code.put(
2725 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2726 Naming.kwds_cname,
2727 Naming.pykwdlist_cname,
2728 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2729 pos_arg_count,
2730 self.name))
2731 code.putln(code.error_goto(self.pos))
2732 code.putln('}')
2734 # convert arg values to their final type and assign them
2735 for i, arg in enumerate(all_args):
2736 if arg.default and not arg.type.is_pyobject:
2737 code.putln("if (values[%d]) {" % i)
2738 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2739 if arg.default and not arg.type.is_pyobject:
2740 code.putln('} else {')
2741 code.putln(
2742 "%s = %s;" % (
2743 arg.entry.cname,
2744 arg.calculate_default_value_code(code)))
2745 code.putln('}')
2747 def generate_argument_conversion_code(self, code):
2748 # Generate code to convert arguments from signature type to
2749 # declared type, if needed. Also copies signature arguments
2750 # into closure fields.
2751 for arg in self.args:
2752 if arg.needs_conversion:
2753 self.generate_arg_conversion(arg, code)
2754 elif arg.entry.in_closure:
2755 code.putln('%s = %s;' % (arg.entry.cname, arg.hdr_cname))
2756 if arg.type.is_pyobject:
2757 code.put_var_incref(arg.entry)
2759 def generate_arg_conversion(self, arg, code):
2760 # Generate conversion code for one argument.
2761 old_type = arg.hdr_type
2762 new_type = arg.type
2763 if old_type.is_pyobject:
2764 if arg.default:
2765 code.putln("if (%s) {" % arg.hdr_cname)
2766 else:
2767 code.putln("assert(%s); {" % arg.hdr_cname)
2768 self.generate_arg_conversion_from_pyobject(arg, code)
2769 code.putln("}")
2770 elif new_type.is_pyobject:
2771 self.generate_arg_conversion_to_pyobject(arg, code)
2772 else:
2773 if new_type.assignable_from(old_type):
2774 code.putln(
2775 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2776 else:
2777 error(arg.pos,
2778 "Cannot convert 1 argument from '%s' to '%s'" %
2779 (old_type, new_type))
2781 def generate_arg_conversion_from_pyobject(self, arg, code):
2782 new_type = arg.type
2783 func = new_type.from_py_function
2784 # copied from CoerceFromPyTypeNode
2785 if func:
2786 lhs = arg.entry.cname
2787 rhs = "%s(%s)" % (func, arg.hdr_cname)
2788 if new_type.is_enum:
2789 rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
2790 code.putln("%s = %s; %s" % (
2791 lhs,
2792 rhs,
2793 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2794 else:
2795 error(arg.pos,
2796 "Cannot convert Python object argument to type '%s'"
2797 % new_type)
2799 def generate_arg_conversion_to_pyobject(self, arg, code):
2800 old_type = arg.hdr_type
2801 func = old_type.to_py_function
2802 if func:
2803 code.putln("%s = %s(%s); %s" % (
2804 arg.entry.cname,
2805 func,
2806 arg.hdr_cname,
2807 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2808 code.put_var_gotref(arg.entry)
2809 else:
2810 error(arg.pos,
2811 "Cannot convert argument of type '%s' to Python object"
2812 % old_type)
2814 def generate_argument_type_tests(self, code):
2815 # Generate type tests for args whose signature
2816 # type is PyObject * and whose declared type is
2817 # a subtype thereof.
2818 for arg in self.args:
2819 if arg.needs_type_test:
2820 self.generate_arg_type_test(arg, code)
2821 elif not arg.accept_none and arg.type.is_pyobject:
2822 self.generate_arg_none_check(arg, code)
2824 def error_value(self):
2825 return self.entry.signature.error_value
2827 def caller_will_check_exceptions(self):
2828 return 1
2830 class OverrideCheckNode(StatNode):
2831 # A Node for dispatching to the def method if it
2832 # is overriden.
2833 #
2834 # py_func
2835 #
2836 # args
2837 # func_temp
2838 # body
2840 child_attrs = ['body']
2842 body = None
2844 def analyse_expressions(self, env):
2845 self.args = env.arg_entries
2846 if self.py_func.is_module_scope:
2847 first_arg = 0
2848 else:
2849 first_arg = 1
2850 import ExprNodes
2851 self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
2852 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2853 call_node = ExprNodes.SimpleCallNode(self.pos,
2854 function=self.func_node,
2855 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2856 self.body = ReturnStatNode(self.pos, value=call_node)
2857 self.body.analyse_expressions(env)
2859 def generate_execution_code(self, code):
2860 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2861 # Check to see if we are an extension type
2862 if self.py_func.is_module_scope:
2863 self_arg = "((PyObject *)%s)" % Naming.module_cname
2864 else:
2865 self_arg = "((PyObject *)%s)" % self.args[0].cname
2866 code.putln("/* Check if called by wrapper */")
2867 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2868 code.putln("/* Check if overriden in Python */")
2869 if self.py_func.is_module_scope:
2870 code.putln("else {")
2871 else:
2872 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2873 func_node_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
2874 self.func_node.set_cname(func_node_temp)
2875 # need to get attribute manually--scope would return cdef method
2876 err = code.error_goto_if_null(func_node_temp, self.pos)
2877 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2878 func_node_temp, self_arg, interned_attr_cname, err))
2879 code.put_gotref(func_node_temp)
2880 is_builtin_function_or_method = "PyCFunction_Check(%s)" % func_node_temp
2881 is_overridden = "(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)" % (
2882 func_node_temp, self.py_func.entry.func_cname)
2883 code.putln("if (!%s || %s) {" % (is_builtin_function_or_method, is_overridden))
2884 self.body.generate_execution_code(code)
2885 code.putln("}")
2886 code.put_decref_clear(func_node_temp, PyrexTypes.py_object_type)
2887 code.funcstate.release_temp(func_node_temp)
2888 code.putln("}")
2890 class ClassDefNode(StatNode, BlockNode):
2891 pass
2893 class PyClassDefNode(ClassDefNode):
2894 # A Python class definition.
2895 #
2896 # name EncodedString Name of the class
2897 # doc string or None
2898 # body StatNode Attribute definition code
2899 # entry Symtab.Entry
2900 # scope PyClassScope
2901 # decorators [DecoratorNode] list of decorators or None
2902 #
2903 # The following subnodes are constructed internally:
2904 #
2905 # dict DictNode Class dictionary
2906 # classobj ClassNode Class object
2907 # target NameNode Variable to assign class object to
2909 child_attrs = ["body", "dict", "classobj", "target"]
2910 decorators = None
2912 def __init__(self, pos, name, bases, doc, body, decorators = None):
2913 StatNode.__init__(self, pos)
2914 self.name = name
2915 self.doc = doc
2916 self.body = body
2917 self.decorators = decorators
2918 import ExprNodes
2919 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2920 if self.doc and Options.docstrings:
2921 doc = embed_position(self.pos, self.doc)
2922 # FIXME: correct string node?
2923 doc_node = ExprNodes.StringNode(pos, value = doc)
2924 else:
2925 doc_node = None
2926 self.classobj = ExprNodes.ClassNode(pos, name = name,
2927 bases = bases, dict = self.dict, doc = doc_node)
2928 self.target = ExprNodes.NameNode(pos, name = name)
2930 def as_cclass(self):
2931 """
2932 Return this node as if it were declared as an extension class
2933 """
2934 bases = self.classobj.bases.args
2935 if len(bases) == 0:
2936 base_class_name = None
2937 base_class_module = None
2938 elif len(bases) == 1:
2939 base = bases[0]
2940 path = []
2941 from ExprNodes import AttributeNode, NameNode
2942 while isinstance(base, AttributeNode):
2943 path.insert(0, base.attribute)
2944 base = base.obj
2945 if isinstance(base, NameNode):
2946 path.insert(0, base.name)
2947 base_class_name = path[-1]
2948 if len(path) > 1:
2949 base_class_module = u'.'.join(path[:-1])
2950 else:
2951 base_class_module = None
2952 else:
2953 error(self.classobj.bases.args.pos, "Invalid base class")
2954 else:
2955 error(self.classobj.bases.args.pos, "C class may only have one base class")
2956 return None
2958 return CClassDefNode(self.pos,
2959 visibility = 'private',
2960 module_name = None,
2961 class_name = self.name,
2962 base_class_module = base_class_module,
2963 base_class_name = base_class_name,
2964 decorators = self.decorators,
2965 body = self.body,
2966 in_pxd = False,
2967 doc = self.doc)
2969 def create_scope(self, env):
2970 genv = env
2971 while env.is_py_class_scope or env.is_c_class_scope:
2972 env = env.outer_scope
2973 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2974 return cenv
2976 def analyse_declarations(self, env):
2977 self.target.analyse_target_declaration(env)
2978 cenv = self.create_scope(env)
2979 cenv.directives = env.directives
2980 cenv.class_obj_cname = self.target.entry.cname
2981 self.body.analyse_declarations(cenv)
2983 def analyse_expressions(self, env):
2984 self.dict.analyse_expressions(env)
2985 self.classobj.analyse_expressions(env)
2986 genv = env.global_scope()
2987 cenv = self.scope
2988 self.body.analyse_expressions(cenv)
2989 self.target.analyse_target_expression(env, self.classobj)
2991 def generate_function_definitions(self, env, code):
2992 self.body.generate_function_definitions(self.scope, code)
2994 def generate_execution_code(self, code):
2995 code.pyclass_stack.append(self)
2996 cenv = self.scope
2997 self.dict.generate_evaluation_code(code)
2998 self.classobj.generate_evaluation_code(code)
2999 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
3000 self.body.generate_execution_code(code)
3001 self.target.generate_assignment_code(self.classobj, code)
3002 self.dict.generate_disposal_code(code)
3003 self.dict.free_temps(code)
3004 code.pyclass_stack.pop()
3007 class CClassDefNode(ClassDefNode):
3008 # An extension type definition.
3009 #
3010 # visibility 'private' or 'public' or 'extern'
3011 # typedef_flag boolean
3012 # api boolean
3013 # module_name string or None For import of extern type objects
3014 # class_name string Unqualified name of class
3015 # as_name string or None Name to declare as in this scope
3016 # base_class_module string or None Module containing the base class
3017 # base_class_name string or None Name of the base class
3018 # objstruct_name string or None Specified C name of object struct
3019 # typeobj_name string or None Specified C name of type object
3020 # in_pxd boolean Is in a .pxd file
3021 # decorators [DecoratorNode] list of decorators or None
3022 # doc string or None
3023 # body StatNode or None
3024 # entry Symtab.Entry
3025 # base_type PyExtensionType or None
3026 # buffer_defaults_node DictNode or None Declares defaults for a buffer
3027 # buffer_defaults_pos
3029 child_attrs = ["body"]
3030 buffer_defaults_node = None
3031 buffer_defaults_pos = None
3032 typedef_flag = False
3033 api = False
3034 objstruct_name = None
3035 typeobj_name = None
3036 decorators = None
3038 def analyse_declarations(self, env):
3039 #print "CClassDefNode.analyse_declarations:", self.class_name
3040 #print "...visibility =", self.visibility
3041 #print "...module_name =", self.module_name
3043 import Buffer
3044 if self.buffer_defaults_node:
3045 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
3046 env, [], self.buffer_defaults_node,
3047 need_complete=False)
3048 else:
3049 buffer_defaults = None
3051 if env.in_cinclude and not self.objstruct_name:
3052 error(self.pos, "Object struct name specification required for "
3053 "C class defined in 'extern from' block")
3054 self.base_type = None
3055 # Now that module imports are cached, we need to
3056 # import the modules for extern classes.
3057 if self.module_name:
3058 self.module = None
3059 for module in env.cimported_modules:
3060 if module.name == self.module_name:
3061 self.module = module
3062 if self.module is None:
3063 self.module = ModuleScope(self.module_name, None, env.context)
3064 self.module.has_extern_class = 1
3065 env.add_imported_module(self.module)
3067 if self.base_class_name:
3068 if self.base_class_module:
3069 base_class_scope = env.find_module(self.base_class_module, self.pos)
3070 else:
3071 base_class_scope = env
3072 if self.base_class_name == 'object':
3073 # extension classes are special and don't need to inherit from object
3074 if base_class_scope is None or base_class_scope.lookup('object') is None:
3075 self.base_class_name = None
3076 self.base_class_module = None
3077 base_class_scope = None
3078 if base_class_scope:
3079 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
3080 if base_class_entry:
3081 if not base_class_entry.is_type:
3082 error(self.pos, "'%s' is not a type name" % self.base_class_name)
3083 elif not base_class_entry.type.is_extension_type:
3084 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
3085 elif not base_class_entry.type.is_complete():
3086 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
3087 else:
3088 self.base_type = base_class_entry.type
3089 has_body = self.body is not None
3090 if self.module_name and self.visibility != 'extern':
3091 module_path = self.module_name.split(".")
3092 home_scope = env.find_imported_module(module_path, self.pos)
3093 if not home_scope:
3094 return
3095 else:
3096 home_scope = env
3098 if self.visibility == 'extern':
3099 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
3100 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
3102 self.entry = home_scope.declare_c_class(
3103 name = self.class_name,
3104 pos = self.pos,
3105 defining = has_body and self.in_pxd,
3106 implementing = has_body and not self.in_pxd,
3107 module_name = self.module_name,
3108 base_type = self.base_type,
3109 objstruct_cname = self.objstruct_name,
3110 typeobj_cname = self.typeobj_name,
3111 visibility = self.visibility,
3112 typedef_flag = self.typedef_flag,
3113 api = self.api,
3114 buffer_defaults = buffer_defaults)
3115 if home_scope is not env and self.visibility == 'extern':
3116 env.add_imported_entry(self.class_name, self.entry, pos)
3117 self.scope = scope = self.entry.type.scope
3118 if scope is not None:
3119 scope.directives = env.directives
3121 if self.doc and Options.docstrings:
3122 scope.doc = embed_position(self.pos, self.doc)
3124 if has_body:
3125 self.body.analyse_declarations(scope)
3126 if self.in_pxd:
3127 scope.defined = 1
3128 else:
3129 scope.implemented = 1
3130 env.allocate_vtable_names(self.entry)
3132 def analyse_expressions(self, env):
3133 if self.body:
3134 scope = self.entry.type.scope
3135 self.body.analyse_expressions(scope)
3137 def generate_function_definitions(self, env, code):
3138 if self.body:
3139 self.body.generate_function_definitions(
3140 self.entry.type.scope, code)
3142 def generate_execution_code(self, code):
3143 # This is needed to generate evaluation code for
3144 # default values of method arguments.
3145 if self.body:
3146 self.body.generate_execution_code(code)
3148 def annotate(self, code):
3149 if self.body:
3150 self.body.annotate(code)
3153 class PropertyNode(StatNode):
3154 # Definition of a property in an extension type.
3155 #
3156 # name string
3157 # doc EncodedString or None Doc string
3158 # body StatListNode
3160 child_attrs = ["body"]
3162 def analyse_declarations(self, env):
3163 entry = env.declare_property(self.name, self.doc, self.pos)
3164 if entry:
3165 entry.scope.directives = env.directives
3166 self.body.analyse_declarations(entry.scope)
3168 def analyse_expressions(self, env):
3169 self.body.analyse_expressions(env)
3171 def generate_function_definitions(self, env, code):
3172 self.body.generate_function_definitions(env, code)
3174 def generate_execution_code(self, code):
3175 pass
3177 def annotate(self, code):
3178 self.body.annotate(code)
3181 class GlobalNode(StatNode):
3182 # Global variable declaration.
3183 #
3184 # names [string]
3186 child_attrs = []
3188 def analyse_declarations(self, env):
3189 for name in self.names:
3190 env.declare_global(name, self.pos)
3192 def analyse_expressions(self, env):
3193 pass
3195 def generate_execution_code(self, code):
3196 pass
3199 class ExprStatNode(StatNode):
3200 # Expression used as a statement.
3201 #
3202 # expr ExprNode
3204 child_attrs = ["expr"]
3206 def analyse_declarations(self, env):
3207 import ExprNodes
3208 if isinstance(self.expr, ExprNodes.GeneralCallNode):
3209 func = self.expr.function.as_cython_attribute()
3210 if func == u'declare':
3211 args, kwds = self.expr.explicit_args_kwds()
3212 if len(args):
3213 error(self.expr.pos, "Variable names must be specified.")
3214 for var, type_node in kwds.key_value_pairs:
3215 type = type_node.analyse_as_type(env)
3216 if type is None:
3217 error(type_node.pos, "Unknown type")
3218 else:
3219 env.declare_var(var.value, type, var.pos, is_cdef = True)
3220 self.__class__ = PassStatNode
3222 def analyse_expressions(self, env):
3223 self.expr.analyse_expressions(env)
3225 def generate_execution_code(self, code):
3226 self.expr.generate_evaluation_code(code)
3227 if not self.expr.is_temp and self.expr.result():
3228 code.putln("%s;" % self.expr.result())
3229 self.expr.generate_disposal_code(code)
3230 self.expr.free_temps(code)
3232 def generate_function_definitions(self, env, code):
3233 self.expr.generate_function_definitions(env, code)
3235 def annotate(self, code):
3236 self.expr.annotate(code)
3239 class AssignmentNode(StatNode):
3240 # Abstract base class for assignment nodes.
3241 #
3242 # The analyse_expressions and generate_execution_code
3243 # phases of assignments are split into two sub-phases
3244 # each, to enable all the right hand sides of a
3245 # parallel assignment to be evaluated before assigning
3246 # to any of the left hand sides.
3248 def analyse_expressions(self, env):
3249 self.analyse_types(env)
3251 # def analyse_expressions(self, env):
3252 # self.analyse_expressions_1(env)
3253 # self.analyse_expressions_2(env)
3255 def generate_execution_code(self, code):
3256 self.generate_rhs_evaluation_code(code)
3257 self.generate_assignment_code(code)
3260 class SingleAssignmentNode(AssignmentNode):
3261 # The simplest case:
3262 #
3263 # a = b
3264 #
3265 # lhs ExprNode Left hand side
3266 # rhs ExprNode Right hand side
3267 # first bool Is this guaranteed the first assignment to lhs?
3269 child_attrs = ["lhs", "rhs"]
3270 first = False
3271 declaration_only = False
3273 def analyse_declarations(self, env):
3274 import ExprNodes
3276 # handle declarations of the form x = cython.foo()
3277 if isinstance(self.rhs, ExprNodes.CallNode):
3278 func_name = self.rhs.function.as_cython_attribute()
3279 if func_name:
3280 args, kwds = self.rhs.explicit_args_kwds()
3282 if func_name in ['declare', 'typedef']:
3283 if len(args) > 2 or kwds is not None:
3284 error(rhs.pos, "Can only declare one type at a time.")
3285 return
3286 type = args[0].analyse_as_type(env)
3287 if type is None:
3288 error(args[0].pos, "Unknown type")
3289 return
3290 lhs = self.lhs
3291 if func_name == 'declare':
3292 if isinstance(lhs, ExprNodes.NameNode):
3293 vars = [(lhs.name, lhs.pos)]
3294 elif isinstance(lhs, ExprNodes.TupleNode):
3295 vars = [(var.name, var.pos) for var in lhs.args]
3296 else:
3297 error(lhs.pos, "Invalid declaration")
3298 return
3299 for var, pos in vars:
3300 env.declare_var(var, type, pos, is_cdef = True)
3301 if len(args) == 2:
3302 # we have a value
3303 self.rhs = args[1]
3304 else:
3305 self.declaration_only = True
3306 else:
3307 self.declaration_only = True
3308 if not isinstance(lhs, ExprNodes.NameNode):
3309 error(lhs.pos, "Invalid declaration.")
3310 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
3312 elif func_name in ['struct', 'union']:
3313 self.declaration_only = True
3314 if len(args) > 0 or kwds is None:
3315 error(rhs.pos, "Struct or union members must be given by name.")
3316 return
3317 members = []
3318 for member, type_node in kwds.key_value_pairs:
3319 type = type_node.analyse_as_type(env)
3320 if type is None:
3321 error(type_node.pos, "Unknown type")
3322 else:
3323 members.append((member.value, type, member.pos))
3324 if len(members) < len(kwds.key_value_pairs):
3325 return
3326 if not isinstance(self.lhs, ExprNodes.NameNode):
3327 error(self.lhs.pos, "Invalid declaration.")
3328 name = self.lhs.name
3329 scope = StructOrUnionScope(name)
3330 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
3331 for member, type, pos in members:
3332 scope.declare_var(member, type, pos)
3334 if self.declaration_only:
3335 return
3336 else:
3337 self.lhs.analyse_target_declaration(env)
3339 def analyse_types(self, env, use_temp = 0):
3340 self.rhs.analyse_types(env)
3341 self.lhs.analyse_target_types(env)
3342 self.lhs.gil_assignment_check(env)
3343 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3344 if use_temp:
3345 self.rhs = self.rhs.coerce_to_temp(env)
3347 def generate_rhs_evaluation_code(self, code):
3348 self.rhs.generate_evaluation_code(code)
3350 def generate_assignment_code(self, code):
3351 self.lhs.generate_assignment_code(self.rhs, code)
3353 def generate_function_definitions(self, env, code):
3354 self.rhs.generate_function_definitions(env, code)
3356 def annotate(self, code):
3357 self.lhs.annotate(code)
3358 self.rhs.annotate(code)
3361 class CascadedAssignmentNode(AssignmentNode):
3362 # An assignment with multiple left hand sides:
3363 #
3364 # a = b = c
3365 #
3366 # lhs_list [ExprNode] Left hand sides
3367 # rhs ExprNode Right hand sides
3368 #
3369 # Used internally:
3370 #
3371 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
3373 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
3374 coerced_rhs_list = None
3376 def analyse_declarations(self, env):
3377 for lhs in self.lhs_list:
3378 lhs.analyse_target_declaration(env)
3380 def analyse_types(self, env, use_temp = 0):
3381 self.rhs.analyse_types(env)
3382 if not self.rhs.is_simple():
3383 if use_temp:
3384 self.rhs = self.rhs.coerce_to_temp(env)
3385 else:
3386 self.rhs = self.rhs.coerce_to_simple(env)
3387 from ExprNodes import CloneNode
3388 self.coerced_rhs_list = []
3389 for lhs in self.lhs_list:
3390 lhs.analyse_target_types(env)
3391 lhs.gil_assignment_check(env)
3392 rhs = CloneNode(self.rhs)
3393 rhs = rhs.coerce_to(lhs.type, env)
3394 self.coerced_rhs_list.append(rhs)
3396 def generate_rhs_evaluation_code(self, code):
3397 self.rhs.generate_evaluation_code(code)
3399 def generate_assignment_code(self, code):
3400 for i in range(len(self.lhs_list)):
3401 lhs = self.lhs_list[i]
3402 rhs = self.coerced_rhs_list[i]
3403 rhs.generate_evaluation_code(code)
3404 lhs.generate_assignment_code(rhs, code)
3405 # Assignment has disposed of the cloned RHS
3406 self.rhs.generate_disposal_code(code)
3407 self.rhs.free_temps(code)
3409 def generate_function_definitions(self, env, code):
3410 self.rhs.generate_function_definitions(env, code)
3412 def annotate(self, code):
3413 for i in range(len(self.lhs_list)):
3414 lhs = self.lhs_list[i].annotate(code)
3415 rhs = self.coerced_rhs_list[i].annotate(code)
3416 self.rhs.annotate(code)
3419 class ParallelAssignmentNode(AssignmentNode):
3420 # A combined packing/unpacking assignment:
3421 #
3422 # a, b, c = d, e, f
3423 #
3424 # This has been rearranged by the parser into
3425 #
3426 # a = d ; b = e ; c = f
3427 #
3428 # but we must evaluate all the right hand sides
3429 # before assigning to any of the left hand sides.
3430 #
3431 # stats [AssignmentNode] The constituent assignments
3433 child_attrs = ["stats"]
3435 def analyse_declarations(self, env):
3436 for stat in self.stats:
3437 stat.analyse_declarations(env)
3439 def analyse_expressions(self, env):
3440 for stat in self.stats:
3441 stat.analyse_types(env, use_temp = 1)
3443 # def analyse_expressions(self, env):
3444 # for stat in self.stats:
3445 # stat.analyse_expressions_1(env, use_temp = 1)
3446 # for stat in self.stats:
3447 # stat.analyse_expressions_2(env)
3449 def generate_execution_code(self, code):
3450 for stat in self.stats:
3451 stat.generate_rhs_evaluation_code(code)
3452 for stat in self.stats:
3453 stat.generate_assignment_code(code)
3455 def generate_function_definitions(self, env, code):
3456 for stat in self.stats:
3457 stat.generate_function_definitions(env, code)
3459 def annotate(self, code):
3460 for stat in self.stats:
3461 stat.annotate(code)
3464 class InPlaceAssignmentNode(AssignmentNode):
3465 # An in place arithmetic operand:
3466 #
3467 # a += b
3468 # a -= b
3469 # ...
3470 #
3471 # lhs ExprNode Left hand side
3472 # rhs ExprNode Right hand side
3473 # op char one of "+-*/%^&|"
3474 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3475 #
3476 # This code is a bit tricky because in order to obey Python
3477 # semantics the sub-expressions (e.g. indices) of the lhs must
3478 # not be evaluated twice. So we must re-use the values calculated
3479 # in evaluation phase for the assignment phase as well.
3480 # Fortunately, the type of the lhs node is fairly constrained
3481 # (it must be a NameNode, AttributeNode, or IndexNode).
3483 child_attrs = ["lhs", "rhs"]
3484 dup = None
3486 def analyse_declarations(self, env):
3487 self.lhs.analyse_target_declaration(env)
3489 def analyse_types(self, env):
3490 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3491 self.rhs.analyse_types(env)
3492 self.lhs.analyse_target_types(env)
3493 import ExprNodes
3494 if self.lhs.type.is_pyobject:
3495 self.rhs = self.rhs.coerce_to_pyobject(env)
3496 elif self.rhs.type.is_pyobject or (self.lhs.type.is_numeric and self.rhs.type.is_numeric):
3497 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3498 if self.lhs.type.is_pyobject:
3499 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3500 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3502 def generate_execution_code(self, code):
3503 import ExprNodes
3504 self.rhs.generate_evaluation_code(code)
3505 self.dup.generate_subexpr_evaluation_code(code)
3506 if self.dup.is_temp:
3507 self.dup.allocate_temp_result(code)
3508 # self.dup.generate_result_code is run only if it is not buffer access
3509 if self.operator == "**":
3510 extra = ", Py_None"
3511 else:
3512 extra = ""
3513 if self.lhs.type.is_pyobject:
3514 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3515 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3516 self.dup.generate_result_code(code)
3517 self.result_value_temp.allocate(code)
3518 code.putln(
3519 "%s = %s(%s, %s%s); %s" % (
3520 self.result_value.result(),
3521 self.py_operation_function(),
3522 self.dup.py_result(),
3523 self.rhs.py_result(),
3524 extra,
3525 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3526 code.put_gotref(self.result_value.py_result())
3527 self.result_value.generate_evaluation_code(code) # May be a type check...
3528 self.rhs.generate_disposal_code(code)
3529 self.rhs.free_temps(code)
3530 self.dup.generate_disposal_code(code)
3531 self.dup.free_temps(code)
3532 self.lhs.generate_assignment_code(self.result_value, code)
3533 self.result_value_temp.release(code)
3534 else:
3535 c_op = self.operator
3536 if c_op == "//":
3537 c_op = "/"
3538 elif c_op == "**":
3539 error(self.pos, "No C inplace power operator")
3540 elif self.lhs.type.is_complex:
3541 error(self.pos, "Inplace operators not implemented for complex types.")
3543 # have to do assignment directly to avoid side-effects
3544 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3545 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3546 else:
3547 self.dup.generate_result_code(code)
3548 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3549 self.rhs.generate_disposal_code(code)
3550 self.rhs.free_temps(code)
3551 if self.dup.is_temp:
3552 self.dup.generate_subexpr_disposal_code(code)
3553 self.dup.free_subexpr_temps(code)
3555 def create_dup_node(self, env):
3556 import ExprNodes
3557 self.dup = self.lhs
3558 self.dup.analyse_types(env)
3559 if isinstance(self.lhs, ExprNodes.NameNode):
3560 target_lhs = ExprNodes.NameNode(self.dup.pos,
3561 name = self.dup.name,
3562 is_temp = self.dup.is_temp,
3563 entry = self.dup.entry)
3564 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3565 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3566 obj = ExprNodes.CloneNode(self.lhs.obj),
3567 attribute = self.dup.attribute,
3568 is_temp = self.dup.is_temp)
3569 elif isinstance(self.lhs, ExprNodes.IndexNode):
3570 if self.lhs.index:
3571 index = ExprNodes.CloneNode(self.lhs.index)
3572 else:
3573 index = None
3574 if self.lhs.indices:
3575 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3576 else:
3577 indices = []
3578 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3579 base = ExprNodes.CloneNode(self.dup.base),
3580 index = index,
3581 indices = indices,
3582 is_temp = self.dup.is_temp)
3583 else:
3584 assert False, "Unsupported node: %s" % type(self.lhs)
3585 self.lhs = target_lhs
3586 return self.dup
3588 def py_operation_function(self):
3589 return self.py_functions[self.operator]
3591 py_functions = {
3592 "|": "PyNumber_InPlaceOr",
3593 "^": "PyNumber_InPlaceXor",
3594 "&": "PyNumber_InPlaceAnd",
3595 "+": "PyNumber_InPlaceAdd",
3596 "-": "PyNumber_InPlaceSubtract",
3597 "*": "PyNumber_InPlaceMultiply",
3598 "/": "__Pyx_PyNumber_InPlaceDivide",
3599 "%": "PyNumber_InPlaceRemainder",
3600 "<<": "PyNumber_InPlaceLshift",
3601 ">>": "PyNumber_InPlaceRshift",
3602 "**": "PyNumber_InPlacePower",
3603 "//": "PyNumber_InPlaceFloorDivide",
3604 }
3606 def annotate(self, code):
3607 self.lhs.annotate(code)
3608 self.rhs.annotate(code)
3609 self.dup.annotate(code)
3611 def create_binop_node(self):
3612 import ExprNodes
3613 return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
3616 class PrintStatNode(StatNode):
3617 # print statement
3618 #
3619 # arg_tuple TupleNode
3620 # stream ExprNode or None (stdout)
3621 # append_newline boolean
3623 child_attrs = ["arg_tuple", "stream"]
3625 def analyse_expressions(self, env):
3626 if self.stream:
3627 self.stream.analyse_expressions(env)
3628 self.stream = self.stream.coerce_to_pyobject(env)
3629 self.arg_tuple.analyse_expressions(env)
3630 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3631 env.use_utility_code(printing_utility_code)
3632 if len(self.arg_tuple.args) == 1 and self.append_newline:
3633 env.use_utility_code(printing_one_utility_code)
3635 nogil_check = Node.gil_error
3636 gil_message = "Python print statement"
3638 def generate_execution_code(self, code):
3639 if self.stream:
3640 self.stream.generate_evaluation_code(code)
3641 stream_result = self.stream.py_result()
3642 else:
3643 stream_result = '0'
3644 if len(self.arg_tuple.args) == 1 and self.append_newline:
3645 arg = self.arg_tuple.args[0]
3646 arg.generate_evaluation_code(code)
3648 code.putln(
3649 "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
3650 stream_result,
3651 arg.py_result(),
3652 code.error_goto(self.pos)))
3653 arg.generate_disposal_code(code)
3654 arg.free_temps(code)
3655 else:
3656 self.arg_tuple.generate_evaluation_code(code)
3657 code.putln(
3658 "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
3659 stream_result,
3660 self.arg_tuple.py_result(),
3661 self.append_newline,
3662 code.error_goto(self.pos)))
3663 self.arg_tuple.generate_disposal_code(code)
3664 self.arg_tuple.free_temps(code)
3666 if self.stream:
3667 self.stream.generate_disposal_code(code)
3668 self.stream.free_temps(code)
3670 def generate_function_definitions(self, env, code):
3671 if self.stream:
3672 self.stream.generate_function_definitions(env, code)
3673 self.arg_tuple.generate_function_definitions(env, code)
3675 def annotate(self, code):
3676 if self.stream:
3677 self.stream.annotate(code)
3678 self.arg_tuple.annotate(code)
3681 class ExecStatNode(StatNode):
3682 # exec statement
3683 #
3684 # args [ExprNode]
3686 child_attrs = ["args"]
3688 def analyse_expressions(self, env):
3689 for i, arg in enumerate(self.args):
3690 arg.analyse_expressions(env)
3691 arg = arg.coerce_to_pyobject(env)
3692 self.args[i] = arg
3693 env.use_utility_code(Builtin.pyexec_utility_code)
3695 nogil_check = Node.gil_error
3696 gil_message = "Python exec statement"
3698 def generate_execution_code(self, code):
3699 args = []
3700 for arg in self.args:
3701 arg.generate_evaluation_code(code)
3702 args.append( arg.py_result() )
3703 args = tuple(args + ['0', '0'][:3-len(args)])
3704 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3705 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3706 (temp_result,) + args))
3707 for arg in self.args:
3708 arg.generate_disposal_code(code)
3709 arg.free_temps(code)
3710 code.putln(
3711 code.error_goto_if_null(temp_result, self.pos))
3712 code.put_gotref(temp_result)
3713 code.put_decref_clear(temp_result, py_object_type)
3714 code.funcstate.release_temp(temp_result)
3716 def annotate(self, code):
3717 for arg in self.args:
3718 arg.annotate(code)
3721 class DelStatNode(StatNode):
3722 # del statement
3723 #
3724 # args [ExprNode]
3726 child_attrs = ["args"]
3728 def analyse_declarations(self, env):
3729 for arg in self.args:
3730 arg.analyse_target_declaration(env)
3732 def analyse_expressions(self, env):
3733 for arg in self.args:
3734 arg.analyse_target_expression(env, None)
3735 if arg.type.is_pyobject:
3736 pass
3737 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3738 self.cpp_check(env)
3739 elif arg.type.is_cpp_class:
3740 error(arg.pos, "Deletion of non-heap C++ object")
3741 else:
3742 error(arg.pos, "Deletion of non-Python, non-C++ object")
3743 #arg.release_target_temp(env)
3745 def nogil_check(self, env):
3746 for arg in self.args:
3747 if arg.type.is_pyobject:
3748 self.gil_error()
3750 gil_message = "Deleting Python object"
3752 def generate_execution_code(self, code):
3753 for arg in self.args:
3754 if arg.type.is_pyobject:
3755 arg.generate_deletion_code(code)
3756 elif arg.type.is_ptr and arg.type.base_type.is_cpp_class:
3757 arg.generate_result_code(code)
3758 code.putln("delete %s;" % arg.result())
3759 # else error reported earlier
3761 def annotate(self, code):
3762 for arg in self.args:
3763 arg.annotate(code)
3766 class PassStatNode(StatNode):
3767 # pass statement
3769 child_attrs = []
3771 def analyse_expressions(self, env):
3772 pass
3774 def generate_execution_code(self, code):
3775 pass
3778 class BreakStatNode(StatNode):
3780 child_attrs = []
3782 def analyse_expressions(self, env):
3783 pass
3785 def generate_execution_code(self, code):
3786 if not code.break_label:
3787 error(self.pos, "break statement not inside loop")
3788 else:
3789 code.put_goto(code.break_label)
3792 class ContinueStatNode(StatNode):
3794 child_attrs = []
3796 def analyse_expressions(self, env):
3797 pass
3799 def generate_execution_code(self, code):
3800 if code.funcstate.in_try_finally:
3801 error(self.pos, "continue statement inside try of try...finally")
3802 elif not code.continue_label:
3803 error(self.pos, "continue statement not inside loop")
3804 else:
3805 code.put_goto(code.continue_label)
3808 class ReturnStatNode(StatNode):
3809 # return statement
3810 #
3811 # value ExprNode or None
3812 # return_type PyrexType
3814 child_attrs = ["value"]
3816 def analyse_expressions(self, env):
3817 return_type = env.return_type
3818 self.return_type = return_type
3819 if not return_type:
3820 error(self.pos, "Return not inside a function body")
3821 return
3822 if self.value:
3823 self.value.analyse_types(env)
3824 if return_type.is_void or return_type.is_returncode:
3825 error(self.value.pos,
3826 "Return with value in void function")
3827 else:
3828 self.value = self.value.coerce_to(env.return_type, env)
3829 else:
3830 if (not return_type.is_void
3831 and not return_type.is_pyobject
3832 and not return_type.is_returncode):
3833 error(self.pos, "Return value required")
3835 def nogil_check(self, env):
3836 if self.return_type.is_pyobject:
3837 self.gil_error()
3839 gil_message = "Returning Python object"
3841 def generate_execution_code(self, code):
3842 code.mark_pos(self.pos)
3843 if not self.return_type:
3844 # error reported earlier
3845 return
3846 if self.return_type.is_pyobject:
3847 code.put_xdecref(Naming.retval_cname,
3848 self.return_type)
3849 if self.value:
3850 self.value.generate_evaluation_code(code)
3851 self.value.make_owned_reference(code)
3852 code.putln(
3853 "%s = %s;" % (
3854 Naming.retval_cname,
3855 self.value.result_as(self.return_type)))
3856 self.value.generate_post_assignment_code(code)
3857 self.value.free_temps(code)
3858 else:
3859 if self.return_type.is_pyobject:
3860 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3861 elif self.return_type.is_returncode:
3862 code.putln(
3863 "%s = %s;" % (
3864 Naming.retval_cname,
3865 self.return_type.default_value))
3866 for cname, type in code.funcstate.temps_holding_reference():
3867 code.put_decref_clear(cname, type)
3868 code.put_goto(code.return_label)
3870 def generate_function_definitions(self, env, code):
3871 if self.value is not None:
3872 self.value.generate_function_definitions(env, code)
3874 def annotate(self, code):
3875 if self.value:
3876 self.value.annotate(code)
3879 class RaiseStatNode(StatNode):
3880 # raise statement
3881 #
3882 # exc_type ExprNode or None
3883 # exc_value ExprNode or None
3884 # exc_tb ExprNode or None
3886 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3888 def analyse_expressions(self, env):
3889 if self.exc_type:
3890 self.exc_type.analyse_types(env)
3891 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3892 if self.exc_value:
3893 self.exc_value.analyse_types(env)
3894 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3895 if self.exc_tb:
3896 self.exc_tb.analyse_types(env)
3897 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3898 env.use_utility_code(raise_utility_code)
3900 nogil_check = Node.gil_error
3901 gil_message = "Raising exception"
3903 def generate_execution_code(self, code):
3904 if self.exc_type:
3905 self.exc_type.generate_evaluation_code(code)
3906 type_code = self.exc_type.py_result()
3907 else:
3908 type_code = "0"
3909 if self.exc_value:
3910 self.exc_value.generate_evaluation_code(code)
3911 value_code = self.exc_value.py_result()
3912 else:
3913 value_code = "0"
3914 if self.exc_tb:
3915 self.exc_tb.generate_evaluation_code(code)
3916 tb_code = self.exc_tb.py_result()
3917 else:
3918 tb_code = "0"
3919 code.putln(
3920 "__Pyx_Raise(%s, %s, %s);" % (
3921 type_code,
3922 value_code,
3923 tb_code))
3924 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3925 if obj:
3926 obj.generate_disposal_code(code)
3927 obj.free_temps(code)
3928 code.putln(
3929 code.error_goto(self.pos))
3931 def generate_function_definitions(self, env, code):
3932 if self.exc_type is not None:
3933 self.exc_type.generate_function_definitions(env, code)
3934 if self.exc_value is not None:
3935 self.exc_value.generate_function_definitions(env, code)
3936 if self.exc_tb is not None:
3937 self.exc_tb.generate_function_definitions(env, code)
3939 def annotate(self, code):
3940 if self.exc_type:
3941 self.exc_type.annotate(code)
3942 if self.exc_value:
3943 self.exc_value.annotate(code)
3944 if self.exc_tb:
3945 self.exc_tb.annotate(code)
3948 class ReraiseStatNode(StatNode):
3950 child_attrs = []
3952 def analyse_expressions(self, env):
3953 env.use_utility_code(restore_exception_utility_code)
3955 nogil_check = Node.gil_error
3956 gil_message = "Raising exception"
3958 def generate_execution_code(self, code):
3959 vars = code.funcstate.exc_vars
3960 if vars:
3961 for varname in vars:
3962 code.put_giveref(varname)
3963 code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
3964 for varname in vars:
3965 code.put("%s = 0; " % varname)
3966 code.putln()
3967 code.putln(code.error_goto(self.pos))
3968 else:
3969 error(self.pos, "Reraise not inside except clause")
3972 class AssertStatNode(StatNode):
3973 # assert statement
3974 #
3975 # cond ExprNode
3976 # value ExprNode or None
3978 child_attrs = ["cond", "value"]
3980 def analyse_expressions(self, env):
3981 self.cond = self.cond.analyse_boolean_expression(env)
3982 if self.value:
3983 self.value.analyse_types(env)
3984 self.value = self.value.coerce_to_pyobject(env)
3986 nogil_check = Node.gil_error
3987 gil_message = "Raising exception"
3989 def generate_execution_code(self, code):
3990 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3991 self.cond.generate_evaluation_code(code)
3992 code.putln(
3993 "if (unlikely(!%s)) {" %
3994 self.cond.result())
3995 if self.value:
3996 self.value.generate_evaluation_code(code)
3997 code.putln(
3998 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3999 self.value.py_result())
4000 self.value.generate_disposal_code(code)
4001 self.value.free_temps(code)
4002 else:
4003 code.putln(
4004 "PyErr_SetNone(PyExc_AssertionError);")
4005 code.putln(
4006 code.error_goto(self.pos))
4007 code.putln(
4008 "}")
4009 self.cond.generate_disposal_code(code)
4010 self.cond.free_temps(code)
4011 code.putln("#endif")
4013 def generate_function_definitions(self, env, code):
4014 self.cond.generate_function_definitions(env, code)
4015 if self.value is not None:
4016 self.value.generate_function_definitions(env, code)
4018 def annotate(self, code):
4019 self.cond.annotate(code)
4020 if self.value:
4021 self.value.annotate(code)
4024 class IfStatNode(StatNode):
4025 # if statement
4026 #
4027 # if_clauses [IfClauseNode]
4028 # else_clause StatNode or None
4030 child_attrs = ["if_clauses", "else_clause"]
4032 def analyse_control_flow(self, env):
4033 env.start_branching(self.pos)
4034 for if_clause in self.if_clauses:
4035 if_clause.analyse_control_flow(env)
4036 env.next_branch(if_clause.end_pos())
4037 if self.else_clause:
4038 self.else_clause.analyse_control_flow(env)
4039 env.finish_branching(self.end_pos())
4041 def analyse_declarations(self, env):
4042 for if_clause in self.if_clauses:
4043 if_clause.analyse_declarations(env)
4044 if self.else_clause:
4045 self.else_clause.analyse_declarations(env)
4047 def analyse_expressions(self, env):
4048 for if_clause in self.if_clauses:
4049 if_clause.analyse_expressions(env)
4050 if self.else_clause:
4051 self.else_clause.analyse_expressions(env)
4053 def generate_execution_code(self, code):
4054 code.mark_pos(self.pos)
4055 end_label = code.new_label()
4056 for if_clause in self.if_clauses:
4057 if_clause.generate_execution_code(code, end_label)
4058 if self.else_clause:
4059 code.putln("/*else*/ {")
4060 self.else_clause.generate_execution_code(code)
4061 code.putln("}")
4062 code.put_label(end_label)
4064 def generate_function_definitions(self, env, code):
4065 for clause in self.if_clauses:
4066 clause.generate_function_definitions(env, code)
4067 if self.else_clause is not None:
4068 self.else_clause.generate_function_definitions(env, code)
4070 def annotate(self, code):
4071 for if_clause in self.if_clauses:
4072 if_clause.annotate(code)
4073 if self.else_clause:
4074 self.else_clause.annotate(code)
4077 class IfClauseNode(Node):
4078 # if or elif clause in an if statement
4079 #
4080 # condition ExprNode
4081 # body StatNode
4083 child_attrs = ["condition", "body"]
4085 def analyse_control_flow(self, env):
4086 self.body.analyse_control_flow(env)
4088 def analyse_declarations(self, env):
4089 self.condition.analyse_declarations(env)
4090 self.body.analyse_declarations(env)
4092 def analyse_expressions(self, env):
4093 self.condition = \
4094 self.condition.analyse_temp_boolean_expression(env)
4095 self.body.analyse_expressions(env)
4097 def get_constant_condition_result(self):
4098 if self.condition.has_constant_result():
4099 return bool(self.condition.constant_result)
4100 else:
4101 return None
4103 def generate_execution_code(self, code, end_label):
4104 self.condition.generate_evaluation_code(code)
4105 code.putln(
4106 "if (%s) {" %
4107 self.condition.result())
4108 self.condition.generate_disposal_code(code)
4109 self.condition.free_temps(code)
4110 self.body.generate_execution_code(code)
4111 code.put_goto(end_label)
4112 code.putln("}")
4114 def generate_function_definitions(self, env, code):
4115 self.condition.generate_function_definitions(env, code)
4116 self.body.generate_function_definitions(env, code)
4118 def annotate(self, code):
4119 self.condition.annotate(code)
4120 self.body.annotate(code)
4123 class SwitchCaseNode(StatNode):
4124 # Generated in the optimization of an if-elif-else node
4125 #
4126 # conditions [ExprNode]
4127 # body StatNode
4129 child_attrs = ['conditions', 'body']
4131 def generate_execution_code(self, code):
4132 for cond in self.conditions:
4133 code.mark_pos(cond.pos)
4134 cond.generate_evaluation_code(code)
4135 code.putln("case %s:" % cond.result())
4136 self.body.generate_execution_code(code)
4137 code.putln("break;")
4139 def generate_function_definitions(self, env, code):
4140 for cond in self.conditions:
4141 cond.generate_function_definitions(env, code)
4142 self.body.generate_function_definitions(env, code)
4144 def annotate(self, code):
4145 for cond in self.conditions:
4146 cond.annotate(code)
4147 self.body.annotate(code)
4149 class SwitchStatNode(StatNode):
4150 # Generated in the optimization of an if-elif-else node
4151 #
4152 # test ExprNode
4153 # cases [SwitchCaseNode]
4154 # else_clause StatNode or None
4156 child_attrs = ['test', 'cases', 'else_clause']
4158 def generate_execution_code(self, code):
4159 code.putln("switch (%s) {" % self.test.result())
4160 for case in self.cases:
4161 case.generate_execution_code(code)
4162 if self.else_clause is not None:
4163 code.putln("default:")
4164 self.else_clause.generate_execution_code(code)
4165 code.putln("break;")
4166 code.putln("}")
4168 def generate_function_definitions(self, env, code):
4169 self.test.generate_function_definitions(env, code)
4170 for case in self.cases:
4171 case.generate_function_definitions(env, code)
4172 if self.else_clause is not None:
4173 self.else_clause.generate_function_definitions(env, code)
4175 def annotate(self, code):
4176 self.test.annotate(code)
4177 for case in self.cases:
4178 case.annotate(code)
4179 if self.else_clause is not None:
4180 self.else_clause.annotate(code)
4182 class LoopNode(object):
4184 def analyse_control_flow(self, env):
4185 env.start_branching(self.pos)
4186 self.body.analyse_control_flow(env)
4187 env.next_branch(self.body.end_pos())
4188 if self.else_clause:
4189 self.else_clause.analyse_control_flow(env)
4190 env.finish_branching(self.end_pos())
4193 class WhileStatNode(LoopNode, StatNode):
4194 # while statement
4195 #
4196 # condition ExprNode
4197 # body StatNode
4198 # else_clause StatNode
4200 child_attrs = ["condition", "body", "else_clause"]
4202 def analyse_declarations(self, env):
4203 self.body.analyse_declarations(env)
4204 if self.else_clause:
4205 self.else_clause.analyse_declarations(env)
4207 def analyse_expressions(self, env):
4208 self.condition = \
4209 self.condition.analyse_temp_boolean_expression(env)
4210 self.body.analyse_expressions(env)
4211 if self.else_clause:
4212 self.else_clause.analyse_expressions(env)
4214 def generate_execution_code(self, code):
4215 old_loop_labels = code.new_loop_labels()
4216 code.putln(
4217 "while (1) {")
4218 self.condition.generate_evaluation_code(code)
4219 self.condition.generate_disposal_code(code)
4220 code.putln(
4221 "if (!%s) break;" %
4222 self.condition.result())
4223 self.condition.free_temps(code)
4224 self.body.generate_execution_code(code)
4225 code.put_label(code.continue_label)
4226 code.putln("}")
4227 break_label = code.break_label
4228 code.set_loop_labels(old_loop_labels)
4229 if self.else_clause:
4230 code.putln("/*else*/ {")
4231 self.else_clause.generate_execution_code(code)
4232 code.putln("}")
4233 code.put_label(break_label)
4235 def generate_function_definitions(self, env, code):
4236 self.condition.generate_function_definitions(env, code)
4237 self.body.generate_function_definitions(env, code)
4238 if self.else_clause is not None:
4239 self.else_clause.generate_function_definitions(env, code)
4241 def annotate(self, code):
4242 self.condition.annotate(code)
4243 self.body.annotate(code)
4244 if self.else_clause:
4245 self.else_clause.annotate(code)
4248 def ForStatNode(pos, **kw):
4249 if 'iterator' in kw:
4250 return ForInStatNode(pos, **kw)
4251 else:
4252 return ForFromStatNode(pos, **kw)
4254 class ForInStatNode(LoopNode, StatNode):
4255 # for statement
4256 #
4257 # target ExprNode
4258 # iterator IteratorNode
4259 # body StatNode
4260 # else_clause StatNode
4261 # item NextNode used internally
4263 child_attrs = ["target", "iterator", "body", "else_clause"]
4264 item = None
4266 def analyse_declarations(self, env):
4267 self.target.analyse_target_declaration(env)
4268 self.body.analyse_declarations(env)
4269 if self.else_clause:
4270 self.else_clause.analyse_declarations(env)
4272 def analyse_expressions(self, env):
4273 import ExprNodes
4274 self.target.analyse_target_types(env)
4275 self.iterator.analyse_expressions(env)
4276 self.item = ExprNodes.NextNode(self.iterator, env)
4277 self.item = self.item.coerce_to(self.target.type, env)
4278 self.body.analyse_expressions(env)
4279 if self.else_clause:
4280 self.else_clause.analyse_expressions(env)
4282 def generate_execution_code(self, code):
4283 old_loop_labels = code.new_loop_labels()
4284 self.iterator.allocate_counter_temp(code)
4285 self.iterator.generate_evaluation_code(code)
4286 code.putln(
4287 "for (;;) {")
4288 self.item.generate_evaluation_code(code)
4289 self.target.generate_assignment_code(self.item, code)
4290 self.body.generate_execution_code(code)
4291 code.put_label(code.continue_label)
4292 code.putln(
4293 "}")
4294 break_label = code.break_label
4295 code.set_loop_labels(old_loop_labels)
4297 if self.else_clause:
4298 # in nested loops, the 'else' block can contain a
4299 # 'continue' statement for the outer loop, but we may need
4300 # to generate cleanup code before taking that path, so we
4301 # intercept it here
4302 orig_continue_label = code.continue_label
4303 code.continue_label = code.new_label('outer_continue')
4305 code.putln("/*else*/ {")
4306 self.else_clause.generate_execution_code(code)
4307 code.putln("}")
4309 if code.label_used(code.continue_label):
4310 code.put_goto(break_label)
4311 code.put_label(code.continue_label)
4312 self.iterator.generate_disposal_code(code)
4313 code.put_goto(orig_continue_label)
4314 code.set_loop_labels(old_loop_labels)
4316 if code.label_used(break_label):
4317 code.put_label(break_label)
4318 self.iterator.release_counter_temp(code)
4319 self.iterator.generate_disposal_code(code)
4320 self.iterator.free_temps(code)
4322 def generate_function_definitions(self, env, code):
4323 self.target.generate_function_definitions(env, code)
4324 self.iterator.generate_function_definitions(env, code)
4325 self.body.generate_function_definitions(env, code)
4326 if self.else_clause is not None:
4327 self.else_clause.generate_function_definitions(env, code)
4329 def annotate(self, code):
4330 self.target.annotate(code)
4331 self.iterator.annotate(code)
4332 self.body.annotate(code)
4333 if self.else_clause:
4334 self.else_clause.annotate(code)
4335 self.item.annotate(code)
4338 class ForFromStatNode(LoopNode, StatNode):
4339 # for name from expr rel name rel expr
4340 #
4341 # target NameNode
4342 # bound1 ExprNode
4343 # relation1 string
4344 # relation2 string
4345 # bound2 ExprNode
4346 # step ExprNode or None
4347 # body StatNode
4348 # else_clause StatNode or None
4349 #
4350 # Used internally:
4351 #
4352 # from_range bool
4353 # is_py_target bool
4354 # loopvar_node ExprNode (usually a NameNode or temp node)
4355 # py_loopvar_node PyTempNode or None
4356 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
4358 is_py_target = False
4359 loopvar_node = None
4360 py_loopvar_node = None
4361 from_range = False
4363 gil_message = "For-loop using object bounds or target"
4365 def nogil_check(self, env):
4366 for x in (self.target, self.bound1, self.bound2):
4367 if x.type.is_pyobject:
4368 self.gil_error()
4370 def analyse_declarations(self, env):
4371 self.target.analyse_target_declaration(env)
4372 self.body.analyse_declarations(env)
4373 if self.else_clause:
4374 self.else_clause.analyse_declarations(env)
4376 def analyse_expressions(self, env):
4377 import ExprNodes
4378 self.target.analyse_target_types(env)
4379 self.bound1.analyse_types(env)
4380 self.bound2.analyse_types(env)
4381 if self.step is not None:
4382 if isinstance(self.step, ExprNodes.UnaryMinusNode):
4383 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
4384 self.step.analyse_types(env)
4386 target_type = self.target.type
4387 if self.target.type.is_numeric:
4388 loop_type = self.target.type
4389 else:
4390 loop_type = PyrexTypes.c_int_type
4391 if not self.bound1.type.is_pyobject:
4392 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
4393 if not self.bound2.type.is_pyobject:
4394 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
4395 if self.step is not None and not self.step.type.is_pyobject:
4396 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
4397 self.bound1 = self.bound1.coerce_to(loop_type, env)
4398 self.bound2 = self.bound2.coerce_to(loop_type, env)
4399 if not self.bound2.is_literal:
4400 self.bound2 = self.bound2.coerce_to_temp(env)
4401 if self.step is not None:
4402 self.step = self.step.coerce_to(loop_type, env)
4403 if not self.step.is_literal:
4404 self.step = self.step.coerce_to_temp(env)
4406 target_type = self.target.type
4407 if not (target_type.is_pyobject or target_type.is_numeric):
4408 error(self.target.pos,
4409 "for-from loop variable must be c numeric type or Python object")
4410 if target_type.is_numeric:
4411 self.is_py_target = False
4412 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
4413 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
4414 self.loopvar_node = self.target
4415 self.py_loopvar_node = None
4416 else:
4417 self.is_py_target = True
4418 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
4419 self.loopvar_node = c_loopvar_node
4420 self.py_loopvar_node = \
4421 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
4422 self.body.analyse_expressions(env)
4423 if self.else_clause:
4424 self.else_clause.analyse_expressions(env)
4426 def generate_execution_code(self, code):
4427 old_loop_labels = code.new_loop_labels()
4428 from_range = self.from_range
4429 self.bound1.generate_evaluation_code(code)
4430 self.bound2.generate_evaluation_code(code)
4431 offset, incop = self.relation_table[self.relation1]
4432 if self.step is not None:
4433 self.step.generate_evaluation_code(code)
4434 step = self.step.result()
4435 incop = "%s=%s" % (incop[0], step)
4436 import ExprNodes
4437 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4438 self.loopvar_node.allocate(code)
4439 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4440 self.py_loopvar_node.allocate(code)
4441 if from_range:
4442 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
4443 else:
4444 loopvar_name = self.loopvar_node.result()
4445 code.putln(
4446 "for (%s = %s%s; %s %s %s; %s%s) {" % (
4447 loopvar_name,
4448 self.bound1.result(), offset,
4449 loopvar_name, self.relation2, self.bound2.result(),
4450 loopvar_name, incop))
4451 if self.py_loopvar_node:
4452 self.py_loopvar_node.generate_evaluation_code(code)
4453 self.target.generate_assignment_code(self.py_loopvar_node, code)
4454 elif from_range:
4455 code.putln("%s = %s;" % (
4456 self.target.result(), loopvar_name))
4457 self.body.generate_execution_code(code)
4458 code.put_label(code.continue_label)
4459 if self.py_loopvar_node:
4460 # This mess is to make for..from loops with python targets behave
4461 # exactly like those with C targets with regards to re-assignment
4462 # of the loop variable.
4463 import ExprNodes
4464 if self.target.entry.is_pyglobal:
4465 # We know target is a NameNode, this is the only ugly case.
4466 target_node = ExprNodes.PyTempNode(self.target.pos, None)
4467 target_node.allocate(code)
4468 interned_cname = code.intern_identifier(self.target.entry.name)
4469 code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
4470 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
4471 target_node.result(),
4472 Naming.module_cname,
4473 interned_cname,
4474 code.error_goto_if_null(target_node.result(), self.target.pos)))
4475 code.put_gotref(target_node.result())
4476 else:
4477 target_node = self.target
4478 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
4479 from_py_node.temp_code = loopvar_name
4480 from_py_node.generate_result_code(code)
4481 if self.target.entry.is_pyglobal:
4482 code.put_decref(target_node.result(), target_node.type)
4483 target_node.release(code)
4484 code.putln("}")
4485 if self.py_loopvar_node:
4486 # This is potentially wasteful, but we don't want the semantics to
4487 # depend on whether or not the loop is a python type.
4488 self.py_loopvar_node.generate_evaluation_code(code)
4489 self.target.generate_assignment_code(self.py_loopvar_node, code)
4490 if from_range:
4491 code.funcstate.release_temp(loopvar_name)
4492 break_label = code.break_label
4493 code.set_loop_labels(old_loop_labels)
4494 if self.else_clause:
4495 code.putln("/*else*/ {")
4496 self.else_clause.generate_execution_code(code)
4497 code.putln("}")
4498 code.put_label(break_label)
4499 self.bound1.generate_disposal_code(code)
4500 self.bound1.free_temps(code)
4501 self.bound2.generate_disposal_code(code)
4502 self.bound2.free_temps(code)
4503 if isinstance(self.loopvar_node, ExprNodes.TempNode):
4504 self.loopvar_node.release(code)
4505 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
4506 self.py_loopvar_node.release(code)
4507 if self.step is not None:
4508 self.step.generate_disposal_code(code)
4509 self.step.free_temps(code)
4511 relation_table = {
4512 # {relop : (initial offset, increment op)}
4513 '<=': ("", "++"),
4514 '<' : ("+1", "++"),
4515 '>=': ("", "--"),
4516 '>' : ("-1", "--")
4517 }
4519 def generate_function_definitions(self, env, code):
4520 self.target.generate_function_definitions(env, code)
4521 self.bound1.generate_function_definitions(env, code)
4522 self.bound2.generate_function_definitions(env, code)
4523 if self.step is not None:
4524 self.step.generate_function_definitions(env, code)
4525 self.body.generate_function_definitions(env, code)
4526 if self.else_clause is not None:
4527 self.else_clause.generate_function_definitions(env, code)
4529 def annotate(self, code):
4530 self.target.annotate(code)
4531 self.bound1.annotate(code)
4532 self.bound2.annotate(code)
4533 if self.step:
4534 self.step.annotate(code)
4535 self.body.annotate(code)
4536 if self.else_clause:
4537 self.else_clause.annotate(code)
4540 class WithStatNode(StatNode):
4541 """
4542 Represents a Python with statement.
4544 This is only used at parse tree level; and is not present in
4545 analysis or generation phases.
4546 """
4547 # manager The with statement manager object
4548 # target Node (lhs expression)
4549 # body StatNode
4550 child_attrs = ["manager", "target", "body"]
4552 class TryExceptStatNode(StatNode):
4553 # try .. except statement
4554 #
4555 # body StatNode
4556 # except_clauses [ExceptClauseNode]
4557 # else_clause StatNode or None
4559 child_attrs = ["body", "except_clauses", "else_clause"]
4561 def analyse_control_flow(self, env):
4562 env.start_branching(self.pos)
4563 self.body.analyse_control_flow(env)
4564 successful_try = env.control_flow # grab this for later
4565 env.next_branch(self.body.end_pos())
4566 env.finish_branching(self.body.end_pos())
4568 env.start_branching(self.except_clauses[0].pos)
4569 for except_clause in self.except_clauses:
4570 except_clause.analyse_control_flow(env)
4571 env.next_branch(except_clause.end_pos())
4573 # the else cause it executed only when the try clause finishes
4574 env.control_flow.incoming = successful_try
4575 if self.else_clause:
4576 self.else_clause.analyse_control_flow(env)
4577 env.finish_branching(self.end_pos())
4579 def analyse_declarations(self, env):
4580 self.body.analyse_declarations(env)
4581 for except_clause in self.except_clauses:
4582 except_clause.analyse_declarations(env)
4583 if self.else_clause:
4584 self.else_clause.analyse_declarations(env)
4585 env.use_utility_code(reset_exception_utility_code)
4587 def analyse_expressions(self, env):
4588 self.body.analyse_expressions(env)
4589 default_clause_seen = 0
4590 for except_clause in self.except_clauses:
4591 except_clause.analyse_expressions(env)
4592 if default_clause_seen:
4593 error(except_clause.pos, "default 'except:' must be last")
4594 if not except_clause.pattern:
4595 default_clause_seen = 1
4596 self.has_default_clause = default_clause_seen
4597 if self.else_clause:
4598 self.else_clause.analyse_expressions(env)
4600 nogil_check = Node.gil_error
4601 gil_message = "Try-except statement"
4603 def generate_execution_code(self, code):
4604 old_return_label = code.return_label
4605 old_break_label = code.break_label
4606 old_continue_label = code.continue_label
4607 old_error_label = code.new_error_label()
4608 our_error_label = code.error_label
4609 except_end_label = code.new_label('exception_handled')
4610 except_error_label = code.new_label('except_error')
4611 except_return_label = code.new_label('except_return')
4612 try_return_label = code.new_label('try_return')
4613 try_break_label = code.new_label('try_break')
4614 try_continue_label = code.new_label('try_continue')
4615 try_end_label = code.new_label('try_end')
4617 code.putln("{")
4618 code.putln("PyObject %s;" %
4619 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4620 code.putln("__Pyx_ExceptionSave(%s);" %
4621 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4622 for var in Naming.exc_save_vars:
4623 code.put_xgotref(var)
4624 code.putln(
4625 "/*try:*/ {")
4626 code.return_label = try_return_label
4627 code.break_label = try_break_label
4628 code.continue_label = try_continue_label
4629 self.body.generate_execution_code(code)
4630 code.putln(
4631 "}")
4632 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4633 code.error_label = except_error_label
4634 code.return_label = except_return_label
4635 if self.else_clause:
4636 code.putln(
4637 "/*else:*/ {")
4638 self.else_clause.generate_execution_code(code)
4639 code.putln(
4640 "}")
4641 for var in Naming.exc_save_vars:
4642 code.put_xdecref_clear(var, py_object_type)
4643 code.put_goto(try_end_label)
4644 if code.label_used(try_return_label):
4645 code.put_label(try_return_label)
4646 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4647 code.putln("__Pyx_ExceptionReset(%s);" %
4648 ', '.join(Naming.exc_save_vars))
4649 code.put_goto(old_return_label)
4650 code.put_label(our_error_label)
4651 for temp_name, type in temps_to_clean_up:
4652 code.put_xdecref_clear(temp_name, type)
4653 for except_clause in self.except_clauses:
4654 except_clause.generate_handling_code(code, except_end_label)
4656 error_label_used = code.label_used(except_error_label)
4657 if error_label_used or not self.has_default_clause:
4658 if error_label_used:
4659 code.put_label(except_error_label)
4660 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4661 code.putln("__Pyx_ExceptionReset(%s);" %
4662 ', '.join(Naming.exc_save_vars))
4663 code.put_goto(old_error_label)
4665 for exit_label, old_label in zip(
4666 [try_break_label, try_continue_label, except_return_label],
4667 [old_break_label, old_continue_label, old_return_label]):
4669 if code.label_used(exit_label):
4670 code.put_label(exit_label)
4671 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4672 code.putln("__Pyx_ExceptionReset(%s);" %
4673 ', '.join(Naming.exc_save_vars))
4674 code.put_goto(old_label)
4676 if code.label_used(except_end_label):
4677 code.put_label(except_end_label)
4678 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4679 code.putln("__Pyx_ExceptionReset(%s);" %
4680 ', '.join(Naming.exc_save_vars))
4681 code.put_label(try_end_label)
4682 code.putln("}")
4684 code.return_label = old_return_label
4685 code.break_label = old_break_label
4686 code.continue_label = old_continue_label
4687 code.error_label = old_error_label
4689 def generate_function_definitions(self, env, code):
4690 self.body.generate_function_definitions(env, code)
4691 for except_clause in self.except_clauses:
4692 except_clause.generate_function_definitions(env, code)
4693 if self.else_clause is not None:
4694 self.else_clause.generate_function_definitions(env, code)
4696 def annotate(self, code):
4697 self.body.annotate(code)
4698 for except_node in self.except_clauses:
4699 except_node.annotate(code)
4700 if self.else_clause:
4701 self.else_clause.annotate(code)
4704 class ExceptClauseNode(Node):
4705 # Part of try ... except statement.
4706 #
4707 # pattern ExprNode
4708 # target ExprNode or None
4709 # body StatNode
4710 # excinfo_target NameNode or None optional target for exception info
4711 # match_flag string result of exception match
4712 # exc_value ExcValueNode used internally
4713 # function_name string qualified name of enclosing function
4714 # exc_vars (string * 3) local exception variables
4716 # excinfo_target is never set by the parser, but can be set by a transform
4717 # in order to extract more extensive information about the exception as a
4718 # sys.exc_info()-style tuple into a target variable
4720 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4722 exc_value = None
4723 excinfo_target = None
4725 def analyse_declarations(self, env):
4726 if self.target:
4727 self.target.analyse_target_declaration(env)
4728 if self.excinfo_target is not None:
4729 self.excinfo_target.analyse_target_declaration(env)
4730 self.body.analyse_declarations(env)
4732 def analyse_expressions(self, env):
4733 import ExprNodes
4734 genv = env.global_scope()
4735 self.function_name = env.qualified_name
4736 if self.pattern:
4737 self.pattern.analyse_expressions(env)
4738 self.pattern = self.pattern.coerce_to_pyobject(env)
4740 if self.target:
4741 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4742 self.target.analyse_target_expression(env, self.exc_value)
4743 if self.excinfo_target is not None:
4744 import ExprNodes
4745 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4746 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4747 self.excinfo_tuple.analyse_expressions(env)
4748 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4750 self.body.analyse_expressions(env)
4752 def generate_handling_code(self, code, end_label):
4753 code.mark_pos(self.pos)
4754 if self.pattern:
4755 self.pattern.generate_evaluation_code(code)
4757 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4758 code.putln(
4759 "%s = PyErr_ExceptionMatches(%s);" % (
4760 match_flag,
4761 self.pattern.py_result()))
4762 self.pattern.generate_disposal_code(code)
4763 self.pattern.free_temps(code)
4764 code.putln(
4765 "if (%s) {" %
4766 match_flag)
4767 code.funcstate.release_temp(match_flag)
4768 else:
4769 code.putln("/*except:*/ {")
4771 if not getattr(self.body, 'stats', True) and \
4772 self.excinfo_target is None and self.target is None:
4773 # most simple case: no exception variable, empty body (pass)
4774 # => reset the exception state, done
4775 code.putln("PyErr_Restore(0,0,0);")
4776 code.put_goto(end_label)
4777 code.putln("}")
4778 return
4780 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4781 manage_ref=True)
4782 for i in xrange(3)]
4783 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4784 # We always have to fetch the exception value even if
4785 # there is no target, because this also normalises the
4786 # exception and stores it in the thread state.
4787 code.globalstate.use_utility_code(get_exception_utility_code)
4788 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4789 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4790 code.error_goto(self.pos)))
4791 for x in exc_vars:
4792 code.put_gotref(x)
4793 if self.target:
4794 self.exc_value.set_var(exc_vars[1])
4795 self.exc_value.generate_evaluation_code(code)
4796 self.target.generate_assignment_code(self.exc_value, code)
4797 if self.excinfo_target is not None:
4798 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4799 node.set_var(tempvar)
4800 self.excinfo_tuple.generate_evaluation_code(code)
4801 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4803 old_break_label, old_continue_label = code.break_label, code.continue_label
4804 code.break_label = code.new_label('except_break')
4805 code.continue_label = code.new_label('except_continue')
4807 old_exc_vars = code.funcstate.exc_vars
4808 code.funcstate.exc_vars = exc_vars
4809 self.body.generate_execution_code(code)
4810 code.funcstate.exc_vars = old_exc_vars
4811 for var in exc_vars:
4812 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4813 code.put_goto(end_label)
4815 if code.label_used(code.break_label):
4816 code.put_label(code.break_label)
4817 for var in exc_vars:
4818 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4819 code.put_goto(old_break_label)
4820 code.break_label = old_break_label
4822 if code.label_used(code.continue_label):
4823 code.put_label(code.continue_label)
4824 for var in exc_vars:
4825 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4826 code.put_goto(old_continue_label)
4827 code.continue_label = old_continue_label
4829 for temp in exc_vars:
4830 code.funcstate.release_temp(temp)
4832 code.putln(
4833 "}")
4835 def generate_function_definitions(self, env, code):
4836 if self.target is not None:
4837 self.target.generate_function_definitions(env, code)
4838 self.body.generate_function_definitions(env, code)
4840 def annotate(self, code):
4841 if self.pattern:
4842 self.pattern.annotate(code)
4843 if self.target:
4844 self.target.annotate(code)
4845 self.body.annotate(code)
4848 class TryFinallyStatNode(StatNode):
4849 # try ... finally statement
4850 #
4851 # body StatNode
4852 # finally_clause StatNode
4853 #
4854 # The plan is that we funnel all continue, break
4855 # return and error gotos into the beginning of the
4856 # finally block, setting a variable to remember which
4857 # one we're doing. At the end of the finally block, we
4858 # switch on the variable to figure out where to go.
4859 # In addition, if we're doing an error, we save the
4860 # exception on entry to the finally block and restore
4861 # it on exit.
4863 child_attrs = ["body", "finally_clause"]
4865 preserve_exception = 1
4867 disallow_continue_in_try_finally = 0
4868 # There doesn't seem to be any point in disallowing
4869 # continue in the try block, since we have no problem
4870 # handling it.
4872 def create_analysed(pos, env, body, finally_clause):
4873 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4874 return node
4875 create_analysed = staticmethod(create_analysed)
4877 def analyse_control_flow(self, env):
4878 env.start_branching(self.pos)
4879 self.body.analyse_control_flow(env)
4880 env.next_branch(self.body.end_pos())
4881 env.finish_branching(self.body.end_pos())
4882 self.finally_clause.analyse_control_flow(env)
4884 def analyse_declarations(self, env):
4885 self.body.analyse_declarations(env)
4886 self.finally_clause.analyse_declarations(env)
4888 def analyse_expressions(self, env):
4889 self.body.analyse_expressions(env)
4890 self.finally_clause.analyse_expressions(env)
4892 nogil_check = Node.gil_error
4893 gil_message = "Try-finally statement"
4895 def generate_execution_code(self, code):
4896 old_error_label = code.error_label
4897 old_labels = code.all_new_labels()
4898 new_labels = code.get_all_labels()
4899 new_error_label = code.error_label
4900 catch_label = code.new_label()
4901 code.putln(
4902 "/*try:*/ {")
4903 if self.disallow_continue_in_try_finally:
4904 was_in_try_finally = code.funcstate.in_try_finally
4905 code.funcstate.in_try_finally = 1
4906 self.body.generate_execution_code(code)
4907 if self.disallow_continue_in_try_finally:
4908 code.funcstate.in_try_finally = was_in_try_finally
4909 code.putln(
4910 "}")
4911 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4912 code.mark_pos(self.finally_clause.pos)
4913 code.putln(
4914 "/*finally:*/ {")
4915 cases_used = []
4916 error_label_used = 0
4917 for i, new_label in enumerate(new_labels):
4918 if new_label in code.labels_used:
4919 cases_used.append(i)
4920 if new_label == new_error_label:
4921 error_label_used = 1
4922 error_label_case = i
4923 if cases_used:
4924 code.putln(
4925 "int __pyx_why;")
4926 if error_label_used and self.preserve_exception:
4927 code.putln(
4928 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4929 code.putln(
4930 "int %s;" % Naming.exc_lineno_name)
4931 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4932 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4933 code.putln(exc_var_init_zero)
4934 else:
4935 exc_var_init_zero = None
4936 code.use_label(catch_label)
4937 code.putln(
4938 "__pyx_why = 0; goto %s;" % catch_label)
4939 for i in cases_used:
4940 new_label = new_labels[i]
4941 #if new_label and new_label != "<try>":
4942 if new_label == new_error_label and self.preserve_exception:
4943 self.put_error_catcher(code,
4944 new_error_label, i+1, catch_label, temps_to_clean_up)
4945 else:
4946 code.put('%s: ' % new_label)
4947 if exc_var_init_zero:
4948 code.putln(exc_var_init_zero)
4949 code.putln("__pyx_why = %s; goto %s;" % (
4950 i+1,
4951 catch_label))
4952 code.put_label(catch_label)
4953 code.set_all_labels(old_labels)
4954 if error_label_used:
4955 code.new_error_label()
4956 finally_error_label = code.error_label
4957 self.finally_clause.generate_execution_code(code)
4958 if error_label_used:
4959 if finally_error_label in code.labels_used and self.preserve_exception:
4960 over_label = code.new_label()
4961 code.put_goto(over_label);
4962 code.put_label(finally_error_label)
4963 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4964 for var in Naming.exc_vars:
4965 code.putln("Py_XDECREF(%s);" % var)
4966 code.putln("}")
4967 code.put_goto(old_error_label)
4968 code.put_label(over_label)
4969 code.error_label = old_error_label
4970 if cases_used:
4971 code.putln(
4972 "switch (__pyx_why) {")
4973 for i in cases_used:
4974 old_label = old_labels[i]
4975 if old_label == old_error_label and self.preserve_exception:
4976 self.put_error_uncatcher(code, i+1, old_error_label)
4977 else:
4978 code.use_label(old_label)
4979 code.putln(
4980 "case %s: goto %s;" % (
4981 i+1,
4982 old_label))
4983 code.putln(
4984 "}")
4985 code.putln(
4986 "}")
4988 def generate_function_definitions(self, env, code):
4989 self.body.generate_function_definitions(env, code)
4990 self.finally_clause.generate_function_definitions(env, code)
4992 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4993 code.globalstate.use_utility_code(restore_exception_utility_code)
4994 code.putln(
4995 "%s: {" %
4996 error_label)
4997 code.putln(
4998 "__pyx_why = %s;" %
4999 i)
5000 for temp_name, type in temps_to_clean_up:
5001 code.put_xdecref_clear(temp_name, type)
5002 code.putln(
5003 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
5004 Naming.exc_vars)
5005 code.putln(
5006 "%s = %s;" % (
5007 Naming.exc_lineno_name, Naming.lineno_cname))
5008 code.put_goto(catch_label)
5009 code.putln("}")
5011 def put_error_uncatcher(self, code, i, error_label):
5012 code.globalstate.use_utility_code(restore_exception_utility_code)
5013 code.putln(
5014 "case %s: {" %
5015 i)
5016 code.putln(
5017 "__Pyx_ErrRestore(%s, %s, %s);" %
5018 Naming.exc_vars)
5019 code.putln(
5020 "%s = %s;" % (
5021 Naming.lineno_cname, Naming.exc_lineno_name))
5022 for var in Naming.exc_vars:
5023 code.putln(
5024 "%s = 0;" %
5025 var)
5026 code.put_goto(error_label)
5027 code.putln(
5028 "}")
5030 def annotate(self, code):
5031 self.body.annotate(code)
5032 self.finally_clause.annotate(code)
5035 class GILStatNode(TryFinallyStatNode):
5036 # 'with gil' or 'with nogil' statement
5037 #
5038 # state string 'gil' or 'nogil'
5040 # child_attrs = []
5042 preserve_exception = 0
5044 def __init__(self, pos, state, body):
5045 self.state = state
5046 TryFinallyStatNode.__init__(self, pos,
5047 body = body,
5048 finally_clause = GILExitNode(pos, state = state))
5050 def analyse_expressions(self, env):
5051 env.use_utility_code(force_init_threads_utility_code)
5052 was_nogil = env.nogil
5053 env.nogil = 1
5054 TryFinallyStatNode.analyse_expressions(self, env)
5055 env.nogil = was_nogil
5057 nogil_check = None
5059 def generate_execution_code(self, code):
5060 code.mark_pos(self.pos)
5061 if self.state == 'gil':
5062 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
5063 else:
5064 code.putln("{ PyThreadState *_save;")
5065 code.putln("Py_UNBLOCK_THREADS")
5066 TryFinallyStatNode.generate_execution_code(self, code)
5067 code.putln("}")
5070 class GILExitNode(StatNode):
5071 # Used as the 'finally' block in a GILStatNode
5072 #
5073 # state string 'gil' or 'nogil'
5075 child_attrs = []
5077 def analyse_expressions(self, env):
5078 pass
5080 def generate_execution_code(self, code):
5081 if self.state == 'gil':
5082 code.putln("PyGILState_Release();")
5083 else:
5084 code.putln("Py_BLOCK_THREADS")
5087 class CImportStatNode(StatNode):
5088 # cimport statement
5089 #
5090 # module_name string Qualified name of module being imported
5091 # as_name string or None Name specified in "as" clause, if any
5093 child_attrs = []
5095 def analyse_declarations(self, env):
5096 if not env.is_module_scope:
5097 error(self.pos, "cimport only allowed at module level")
5098 return
5099 module_scope = env.find_module(self.module_name, self.pos)
5100 if "." in self.module_name:
5101 names = [EncodedString(name) for name in self.module_name.split(".")]
5102 top_name = names[0]
5103 top_module_scope = env.context.find_submodule(top_name)
5104 module_scope = top_module_scope
5105 for name in names[1:]:
5106 submodule_scope = module_scope.find_submodule(name)
5107 module_scope.declare_module(name, submodule_scope, self.pos)
5108 module_scope = submodule_scope
5109 if self.as_name:
5110 env.declare_module(self.as_name, module_scope, self.pos)
5111 else:
5112 env.declare_module(top_name, top_module_scope, self.pos)
5113 else:
5114 name = self.as_name or self.module_name
5115 env.declare_module(name, module_scope, self.pos)
5117 def analyse_expressions(self, env):
5118 pass
5120 def generate_execution_code(self, code):
5121 pass
5124 class FromCImportStatNode(StatNode):
5125 # from ... cimport statement
5126 #
5127 # module_name string Qualified name of module
5128 # imported_names [(pos, name, as_name, kind)] Names to be imported
5130 child_attrs = []
5132 def analyse_declarations(self, env):
5133 if not env.is_module_scope:
5134 error(self.pos, "cimport only allowed at module level")
5135 return
5136 module_scope = env.find_module(self.module_name, self.pos)
5137 env.add_imported_module(module_scope)
5138 for pos, name, as_name, kind in self.imported_names:
5139 if name == "*":
5140 for local_name, entry in module_scope.entries.items():
5141 env.add_imported_entry(local_name, entry, pos)
5142 else:
5143 entry = module_scope.lookup(name)
5144 if entry:
5145 if kind and not self.declaration_matches(entry, kind):
5146 entry.redeclared(pos)
5147 else:
5148 if kind == 'struct' or kind == 'union':
5149 entry = module_scope.declare_struct_or_union(name,
5150 kind = kind, scope = None, typedef_flag = 0, pos = pos)
5151 elif kind == 'class':
5152 entry = module_scope.declare_c_class(name, pos = pos,
5153 module_name = self.module_name)
5154 else:
5155 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
5156 if submodule_scope.parent_module is module_scope:
5157 env.declare_module(as_name or name, submodule_scope, self.pos)
5158 else:
5159 error(pos, "Name '%s' not declared in module '%s'"
5160 % (name, self.module_name))
5162 if entry:
5163 local_name = as_name or name
5164 env.add_imported_entry(local_name, entry, pos)
5166 def declaration_matches(self, entry, kind):
5167 if not entry.is_type:
5168 return 0
5169 type = entry.type
5170 if kind == 'class':
5171 if not type.is_extension_type:
5172 return 0
5173 else:
5174 if not type.is_struct_or_union:
5175 return 0
5176 if kind != type.kind:
5177 return 0
5178 return 1
5180 def analyse_expressions(self, env):
5181 pass
5183 def generate_execution_code(self, code):
5184 pass
5187 class FromImportStatNode(StatNode):
5188 # from ... import statement
5189 #
5190 # module ImportNode
5191 # items [(string, NameNode)]
5192 # interned_items [(string, NameNode, ExprNode)]
5193 # item PyTempNode used internally
5194 # import_star boolean used internally
5196 child_attrs = ["module"]
5197 import_star = 0
5199 def analyse_declarations(self, env):
5200 for name, target in self.items:
5201 if name == "*":
5202 if not env.is_module_scope:
5203 error(self.pos, "import * only allowed at module level")
5204 return
5205 env.has_import_star = 1
5206 self.import_star = 1
5207 else:
5208 target.analyse_target_declaration(env)
5210 def analyse_expressions(self, env):
5211 import ExprNodes
5212 self.module.analyse_expressions(env)
5213 self.item = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
5214 self.interned_items = []
5215 for name, target in self.items:
5216 if name == '*':
5217 for _, entry in env.entries.items():
5218 if not entry.is_type and entry.type.is_extension_type:
5219 env.use_utility_code(ExprNodes.type_test_utility_code)
5220 break
5221 else:
5222 entry = env.lookup(target.name)
5223 # check whether or not entry is already cimported
5224 if (entry.is_type and entry.type.name == name
5225 and hasattr(entry.type, 'module_name')):
5226 if entry.type.module_name == self.module.module_name.value:
5227 # cimported with absolute name
5228 continue
5229 try:
5230 # cimported with relative name
5231 module = env.find_module(self.module.module_name.value,
5232 pos=None)
5233 if entry.type.module_name == module.qualified_name:
5234 continue
5235 except AttributeError:
5236 pass
5237 target.analyse_target_expression(env, None)
5238 if target.type is py_object_type:
5239 coerced_item = None
5240 else:
5241 coerced_item = self.item.coerce_to(target.type, env)
5242 self.interned_items.append((name, target, coerced_item))
5244 def generate_execution_code(self, code):
5245 self.module.generate_evaluation_code(code)
5246 if self.import_star:
5247 code.putln(
5248 'if (%s(%s) < 0) %s;' % (
5249 Naming.import_star,
5250 self.module.py_result(),
5251 code.error_goto(self.pos)))
5252 item_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
5253 self.item.set_cname(item_temp)
5254 for name, target, coerced_item in self.interned_items:
5255 cname = code.intern_identifier(name)
5256 code.putln(
5257 '%s = PyObject_GetAttr(%s, %s); %s' % (
5258 item_temp,
5259 self.module.py_result(),
5260 cname,
5261 code.error_goto_if_null(item_temp, self.pos)))
5262 code.put_gotref(item_temp)
5263 if coerced_item is None:
5264 target.generate_assignment_code(self.item, code)
5265 else:
5266 coerced_item.allocate_temp_result(code)
5267 coerced_item.generate_result_code(code)
5268 target.generate_assignment_code(coerced_item, code)
5269 code.put_decref_clear(item_temp, py_object_type)
5270 code.funcstate.release_temp(item_temp)
5271 self.module.generate_disposal_code(code)
5272 self.module.free_temps(code)
5276 #------------------------------------------------------------------------------------
5277 #
5278 # Runtime support code
5279 #
5280 #------------------------------------------------------------------------------------
5282 utility_function_predeclarations = \
5283 """
5284 /* inline attribute */
5285 #ifndef CYTHON_INLINE
5286 #if defined(__GNUC__)
5287 #define CYTHON_INLINE __inline__
5288 #elif defined(_MSC_VER)
5289 #define CYTHON_INLINE __inline
5290 #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
5291 #define CYTHON_INLINE inline
5292 #else
5293 #define CYTHON_INLINE
5294 #endif
5295 #endif
5297 /* unused attribute */
5298 #ifndef CYTHON_UNUSED
5299 # if defined(__GNUC__)
5300 # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
5301 # define CYTHON_UNUSED __attribute__ ((__unused__))
5302 # else
5303 # define CYTHON_UNUSED
5304 # endif
5305 # elif defined(__ICC) || defined(__INTEL_COMPILER)
5306 # define CYTHON_UNUSED __attribute__ ((__unused__))
5307 # else
5308 # define CYTHON_UNUSED
5309 # endif
5310 #endif
5312 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*/
5314 """
5316 if Options.gcc_branch_hints:
5317 branch_prediction_macros = \
5318 """
5319 #ifdef __GNUC__
5320 /* Test for GCC > 2.95 */
5321 #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
5322 #define likely(x) __builtin_expect(!!(x), 1)
5323 #define unlikely(x) __builtin_expect(!!(x), 0)
5324 #else /* __GNUC__ > 2 ... */
5325 #define likely(x) (x)
5326 #define unlikely(x) (x)
5327 #endif /* __GNUC__ > 2 ... */
5328 #else /* __GNUC__ */
5329 #define likely(x) (x)
5330 #define unlikely(x) (x)
5331 #endif /* __GNUC__ */
5332 """
5333 else:
5334 branch_prediction_macros = \
5335 """
5336 #define likely(x) (x)
5337 #define unlikely(x) (x)
5338 """
5340 #get_name_predeclaration = \
5341 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
5343 #get_name_interned_predeclaration = \
5344 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
5346 #------------------------------------------------------------------------------------
5348 printing_utility_code = UtilityCode(
5349 proto = """
5350 static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/
5351 #if PY_MAJOR_VERSION >= 3
5352 static PyObject* %s = 0;
5353 static PyObject* %s = 0;
5354 #endif
5355 """ % (Naming.print_function, Naming.print_function_kwargs),
5356 cleanup = """
5357 #if PY_MAJOR_VERSION >= 3
5358 Py_CLEAR(%s);
5359 Py_CLEAR(%s);
5360 #endif
5361 """ % (Naming.print_function, Naming.print_function_kwargs),
5362 impl = r"""
5363 #if PY_MAJOR_VERSION < 3
5364 static PyObject *__Pyx_GetStdout(void) {
5365 PyObject *f = PySys_GetObject((char *)"stdout");
5366 if (!f) {
5367 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
5368 }
5369 return f;
5370 }
5372 static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
5373 PyObject* v;
5374 int i;
5376 if (!f) {
5377 if (!(f = __Pyx_GetStdout()))
5378 return -1;
5379 }
5380 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
5381 if (PyFile_SoftSpace(f, 1)) {
5382 if (PyFile_WriteString(" ", f) < 0)
5383 return -1;
5384 }
5385 v = PyTuple_GET_ITEM(arg_tuple, i);
5386 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
5387 return -1;
5388 if (PyString_Check(v)) {
5389 char *s = PyString_AsString(v);
5390 Py_ssize_t len = PyString_Size(v);
5391 if (len > 0 &&
5392 isspace(Py_CHARMASK(s[len-1])) &&
5393 s[len-1] != ' ')
5394 PyFile_SoftSpace(f, 0);
5395 }
5396 }
5397 if (newline) {
5398 if (PyFile_WriteString("\n", f) < 0)
5399 return -1;
5400 PyFile_SoftSpace(f, 0);
5401 }
5402 return 0;
5403 }
5405 #else /* Python 3 has a print function */
5407 static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
5408 PyObject* kwargs = 0;
5409 PyObject* result = 0;
5410 PyObject* end_string;
5411 if (unlikely(!%(PRINT_FUNCTION)s)) {
5412 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
5413 if (!%(PRINT_FUNCTION)s)
5414 return -1;
5415 }
5416 if (stream) {
5417 kwargs = PyDict_New();
5418 if (unlikely(!kwargs))
5419 return -1;
5420 if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0))
5421 goto bad;
5422 if (!newline) {
5423 end_string = PyUnicode_FromStringAndSize(" ", 1);
5424 if (unlikely(!end_string))
5425 goto bad;
5426 if (PyDict_SetItemString(kwargs, "end", end_string) < 0) {
5427 Py_DECREF(end_string);
5428 goto bad;
5429 }
5430 Py_DECREF(end_string);
5431 }
5432 } else if (!newline) {
5433 if (unlikely(!%(PRINT_KWARGS)s)) {
5434 %(PRINT_KWARGS)s = PyDict_New();
5435 if (unlikely(!%(PRINT_KWARGS)s))
5436 return -1;
5437 end_string = PyUnicode_FromStringAndSize(" ", 1);
5438 if (unlikely(!end_string))
5439 return -1;
5440 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
5441 Py_DECREF(end_string);
5442 return -1;
5443 }
5444 Py_DECREF(end_string);
5445 }
5446 kwargs = %(PRINT_KWARGS)s;
5447 }
5448 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
5449 if (unlikely(kwargs) && (kwargs != %(PRINT_KWARGS)s))
5450 Py_DECREF(kwargs);
5451 if (!result)
5452 return -1;
5453 Py_DECREF(result);
5454 return 0;
5455 bad:
5456 if (kwargs != %(PRINT_KWARGS)s)
5457 Py_XDECREF(kwargs);
5458 return -1;
5459 }
5461 #endif
5462 """ % {'BUILTINS' : Naming.builtins_cname,
5463 'PRINT_FUNCTION' : Naming.print_function,
5464 'PRINT_KWARGS' : Naming.print_function_kwargs}
5465 )
5468 printing_one_utility_code = UtilityCode(
5469 proto = """
5470 static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/
5471 """,
5472 impl = r"""
5473 #if PY_MAJOR_VERSION < 3
5475 static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
5476 if (!f) {
5477 if (!(f = __Pyx_GetStdout()))
5478 return -1;
5479 }
5480 if (PyFile_SoftSpace(f, 0)) {
5481 if (PyFile_WriteString(" ", f) < 0)
5482 return -1;
5483 }
5484 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
5485 return -1;
5486 if (PyFile_WriteString("\n", f) < 0)
5487 return -1;
5488 return 0;
5489 /* the line below is just to avoid compiler
5490 * compiler warnings about unused functions */
5491 return __Pyx_Print(f, NULL, 0);
5492 }
5494 #else /* Python 3 has a print function */
5496 static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
5497 int res;
5498 PyObject* arg_tuple = PyTuple_New(1);
5499 if (unlikely(!arg_tuple))
5500 return -1;
5501 Py_INCREF(o);
5502 PyTuple_SET_ITEM(arg_tuple, 0, o);
5503 res = __Pyx_Print(stream, arg_tuple, 1);
5504 Py_DECREF(arg_tuple);
5505 return res;
5506 }
5508 #endif
5509 """,
5510 requires=[printing_utility_code])
5514 #------------------------------------------------------------------------------------
5516 # Exception raising code
5517 #
5518 # Exceptions are raised by __Pyx_Raise() and stored as plain
5519 # type/value/tb in PyThreadState->curexc_*. When being caught by an
5520 # 'except' statement, curexc_* is moved over to exc_* by
5521 # __Pyx_GetException()
5523 restore_exception_utility_code = UtilityCode(
5524 proto = """
5525 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5526 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5527 """,
5528 impl = """
5529 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5530 PyObject *tmp_type, *tmp_value, *tmp_tb;
5531 PyThreadState *tstate = PyThreadState_GET();
5533 tmp_type = tstate->curexc_type;
5534 tmp_value = tstate->curexc_value;
5535 tmp_tb = tstate->curexc_traceback;
5536 tstate->curexc_type = type;
5537 tstate->curexc_value = value;
5538 tstate->curexc_traceback = tb;
5539 Py_XDECREF(tmp_type);
5540 Py_XDECREF(tmp_value);
5541 Py_XDECREF(tmp_tb);
5542 }
5544 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5545 PyThreadState *tstate = PyThreadState_GET();
5546 *type = tstate->curexc_type;
5547 *value = tstate->curexc_value;
5548 *tb = tstate->curexc_traceback;
5550 tstate->curexc_type = 0;
5551 tstate->curexc_value = 0;
5552 tstate->curexc_traceback = 0;
5553 }
5555 """)
5557 # The following function is based on do_raise() from ceval.c. There
5558 # are separate versions for Python2 and Python3 as exception handling
5559 # has changed quite a lot between the two versions.
5561 raise_utility_code = UtilityCode(
5562 proto = """
5563 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5564 """,
5565 impl = """
5566 #if PY_MAJOR_VERSION < 3
5567 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5568 Py_XINCREF(type);
5569 Py_XINCREF(value);
5570 Py_XINCREF(tb);
5571 /* First, check the traceback argument, replacing None with NULL. */
5572 if (tb == Py_None) {
5573 Py_DECREF(tb);
5574 tb = 0;
5575 }
5576 else if (tb != NULL && !PyTraceBack_Check(tb)) {
5577 PyErr_SetString(PyExc_TypeError,
5578 "raise: arg 3 must be a traceback or None");
5579 goto raise_error;
5580 }
5581 /* Next, replace a missing value with None */
5582 if (value == NULL) {
5583 value = Py_None;
5584 Py_INCREF(value);
5585 }
5586 #if PY_VERSION_HEX < 0x02050000
5587 if (!PyClass_Check(type))
5588 #else
5589 if (!PyType_Check(type))
5590 #endif
5591 {
5592 /* Raising an instance. The value should be a dummy. */
5593 if (value != Py_None) {
5594 PyErr_SetString(PyExc_TypeError,
5595 "instance exception may not have a separate value");
5596 goto raise_error;
5597 }
5598 /* Normalize to raise <class>, <instance> */
5599 Py_DECREF(value);
5600 value = type;
5601 #if PY_VERSION_HEX < 0x02050000
5602 if (PyInstance_Check(type)) {
5603 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
5604 Py_INCREF(type);
5605 }
5606 else {
5607 type = 0;
5608 PyErr_SetString(PyExc_TypeError,
5609 "raise: exception must be an old-style class or instance");
5610 goto raise_error;
5611 }
5612 #else
5613 type = (PyObject*) Py_TYPE(type);
5614 Py_INCREF(type);
5615 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
5616 PyErr_SetString(PyExc_TypeError,
5617 "raise: exception class must be a subclass of BaseException");
5618 goto raise_error;
5619 }
5620 #endif
5621 }
5623 __Pyx_ErrRestore(type, value, tb);
5624 return;
5625 raise_error:
5626 Py_XDECREF(value);
5627 Py_XDECREF(type);
5628 Py_XDECREF(tb);
5629 return;
5630 }
5632 #else /* Python 3+ */
5634 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
5635 if (tb == Py_None) {
5636 tb = 0;
5637 } else if (tb && !PyTraceBack_Check(tb)) {
5638 PyErr_SetString(PyExc_TypeError,
5639 "raise: arg 3 must be a traceback or None");
5640 goto bad;
5641 }
5642 if (value == Py_None)
5643 value = 0;
5645 if (PyExceptionInstance_Check(type)) {
5646 if (value) {
5647 PyErr_SetString(PyExc_TypeError,
5648 "instance exception may not have a separate value");
5649 goto bad;
5650 }
5651 value = type;
5652 type = (PyObject*) Py_TYPE(value);
5653 } else if (!PyExceptionClass_Check(type)) {
5654 PyErr_SetString(PyExc_TypeError,
5655 "raise: exception class must be a subclass of BaseException");
5656 goto bad;
5657 }
5659 PyErr_SetObject(type, value);
5661 if (tb) {
5662 PyThreadState *tstate = PyThreadState_GET();
5663 PyObject* tmp_tb = tstate->curexc_traceback;
5664 if (tb != tmp_tb) {
5665 Py_INCREF(tb);
5666 tstate->curexc_traceback = tb;
5667 Py_XDECREF(tmp_tb);
5668 }
5669 }
5671 bad:
5672 return;
5673 }
5674 #endif
5675 """,
5676 requires=[restore_exception_utility_code])
5678 #------------------------------------------------------------------------------------
5680 get_exception_utility_code = UtilityCode(
5681 proto = """
5682 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5683 """,
5684 impl = """
5685 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5686 PyObject *local_type, *local_value, *local_tb;
5687 PyObject *tmp_type, *tmp_value, *tmp_tb;
5688 PyThreadState *tstate = PyThreadState_GET();
5689 local_type = tstate->curexc_type;
5690 local_value = tstate->curexc_value;
5691 local_tb = tstate->curexc_traceback;
5692 tstate->curexc_type = 0;
5693 tstate->curexc_value = 0;
5694 tstate->curexc_traceback = 0;
5695 PyErr_NormalizeException(&local_type, &local_value, &local_tb);
5696 if (unlikely(tstate->curexc_type))
5697 goto bad;
5698 #if PY_MAJOR_VERSION >= 3
5699 if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
5700 goto bad;
5701 #endif
5702 *type = local_type;
5703 *value = local_value;
5704 *tb = local_tb;
5705 Py_INCREF(local_type);
5706 Py_INCREF(local_value);
5707 Py_INCREF(local_tb);
5708 tmp_type = tstate->exc_type;
5709 tmp_value = tstate->exc_value;
5710 tmp_tb = tstate->exc_traceback;
5711 tstate->exc_type = local_type;
5712 tstate->exc_value = local_value;
5713 tstate->exc_traceback = local_tb;
5714 /* Make sure tstate is in a consistent state when we XDECREF
5715 these objects (XDECREF may run arbitrary code). */
5716 Py_XDECREF(tmp_type);
5717 Py_XDECREF(tmp_value);
5718 Py_XDECREF(tmp_tb);
5719 return 0;
5720 bad:
5721 *type = 0;
5722 *value = 0;
5723 *tb = 0;
5724 Py_XDECREF(local_type);
5725 Py_XDECREF(local_value);
5726 Py_XDECREF(local_tb);
5727 return -1;
5728 }
5730 """)
5732 #------------------------------------------------------------------------------------
5734 get_exception_tuple_utility_code = UtilityCode(proto="""
5735 static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
5736 """,
5737 # I doubt that calling __Pyx_GetException() here is correct as it moves
5738 # the exception from tstate->curexc_* to tstate->exc_*, which prevents
5739 # exception handlers later on from receiving it.
5740 impl = """
5741 static PyObject *__Pyx_GetExceptionTuple(void) {
5742 PyObject *type = NULL, *value = NULL, *tb = NULL;
5743 if (__Pyx_GetException(&type, &value, &tb) == 0) {
5744 PyObject* exc_info = PyTuple_New(3);
5745 if (exc_info) {
5746 Py_INCREF(type);
5747 Py_INCREF(value);
5748 Py_INCREF(tb);
5749 PyTuple_SET_ITEM(exc_info, 0, type);
5750 PyTuple_SET_ITEM(exc_info, 1, value);
5751 PyTuple_SET_ITEM(exc_info, 2, tb);
5752 return exc_info;
5753 }
5754 }
5755 return NULL;
5756 }
5757 """,
5758 requires=[get_exception_utility_code])
5760 #------------------------------------------------------------------------------------
5762 reset_exception_utility_code = UtilityCode(
5763 proto = """
5764 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5765 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5766 """,
5767 impl = """
5768 static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5769 PyThreadState *tstate = PyThreadState_GET();
5770 *type = tstate->exc_type;
5771 *value = tstate->exc_value;
5772 *tb = tstate->exc_traceback;
5773 Py_XINCREF(*type);
5774 Py_XINCREF(*value);
5775 Py_XINCREF(*tb);
5776 }
5778 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5779 PyObject *tmp_type, *tmp_value, *tmp_tb;
5780 PyThreadState *tstate = PyThreadState_GET();
5781 tmp_type = tstate->exc_type;
5782 tmp_value = tstate->exc_value;
5783 tmp_tb = tstate->exc_traceback;
5784 tstate->exc_type = type;
5785 tstate->exc_value = value;
5786 tstate->exc_traceback = tb;
5787 Py_XDECREF(tmp_type);
5788 Py_XDECREF(tmp_value);
5789 Py_XDECREF(tmp_tb);
5790 }
5791 """)
5793 #------------------------------------------------------------------------------------
5795 arg_type_test_utility_code = UtilityCode(
5796 proto = """
5797 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5798 const char *name, int exact); /*proto*/
5799 """,
5800 impl = """
5801 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5802 const char *name, int exact)
5803 {
5804 if (!type) {
5805 PyErr_Format(PyExc_SystemError, "Missing type object");
5806 return 0;
5807 }
5808 if (none_allowed && obj == Py_None) return 1;
5809 else if (exact) {
5810 if (Py_TYPE(obj) == type) return 1;
5811 }
5812 else {
5813 if (PyObject_TypeCheck(obj, type)) return 1;
5814 }
5815 PyErr_Format(PyExc_TypeError,
5816 "Argument '%s' has incorrect type (expected %s, got %s)",
5817 name, type->tp_name, Py_TYPE(obj)->tp_name);
5818 return 0;
5819 }
5820 """)
5822 #------------------------------------------------------------------------------------
5823 #
5824 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5825 # many or too few positional arguments were found. This handles
5826 # Py_ssize_t formatting correctly.
5828 raise_argtuple_invalid_utility_code = UtilityCode(
5829 proto = """
5830 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5831 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5832 """,
5833 impl = """
5834 static void __Pyx_RaiseArgtupleInvalid(
5835 const char* func_name,
5836 int exact,
5837 Py_ssize_t num_min,
5838 Py_ssize_t num_max,
5839 Py_ssize_t num_found)
5840 {
5841 Py_ssize_t num_expected;
5842 const char *number, *more_or_less;
5844 if (num_found < num_min) {
5845 num_expected = num_min;
5846 more_or_less = "at least";
5847 } else {
5848 num_expected = num_max;
5849 more_or_less = "at most";
5850 }
5851 if (exact) {
5852 more_or_less = "exactly";
5853 }
5854 number = (num_expected == 1) ? "" : "s";
5855 PyErr_Format(PyExc_TypeError,
5856 #if PY_VERSION_HEX < 0x02050000
5857 "%s() takes %s %d positional argument%s (%d given)",
5858 #else
5859 "%s() takes %s %zd positional argument%s (%zd given)",
5860 #endif
5861 func_name, more_or_less, num_expected, number, num_found);
5862 }
5863 """)
5865 raise_keyword_required_utility_code = UtilityCode(
5866 proto = """
5867 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5868 """,
5869 impl = """
5870 static CYTHON_INLINE void __Pyx_RaiseKeywordRequired(
5871 const char* func_name,
5872 PyObject* kw_name)
5873 {
5874 PyErr_Format(PyExc_TypeError,
5875 #if PY_MAJOR_VERSION >= 3
5876 "%s() needs keyword-only argument %U", func_name, kw_name);
5877 #else
5878 "%s() needs keyword-only argument %s", func_name,
5879 PyString_AS_STRING(kw_name));
5880 #endif
5881 }
5882 """)
5884 raise_double_keywords_utility_code = UtilityCode(
5885 proto = """
5886 static void __Pyx_RaiseDoubleKeywordsError(
5887 const char* func_name, PyObject* kw_name); /*proto*/
5888 """,
5889 impl = """
5890 static void __Pyx_RaiseDoubleKeywordsError(
5891 const char* func_name,
5892 PyObject* kw_name)
5893 {
5894 PyErr_Format(PyExc_TypeError,
5895 #if PY_MAJOR_VERSION >= 3
5896 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5897 #else
5898 "%s() got multiple values for keyword argument '%s'", func_name,
5899 PyString_AS_STRING(kw_name));
5900 #endif
5901 }
5902 """)
5904 #------------------------------------------------------------------------------------
5905 #
5906 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5907 # were passed to a function, or if any keywords were passed to a
5908 # function that does not accept them.
5910 keyword_string_check_utility_code = UtilityCode(
5911 proto = """
5912 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5913 const char* function_name, int kw_allowed); /*proto*/
5914 """,
5915 impl = """
5916 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
5917 PyObject *kwdict,
5918 const char* function_name,
5919 int kw_allowed)
5920 {
5921 PyObject* key = 0;
5922 Py_ssize_t pos = 0;
5923 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5924 #if PY_MAJOR_VERSION < 3
5925 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5926 #else
5927 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5928 #endif
5929 goto invalid_keyword_type;
5930 }
5931 if ((!kw_allowed) && unlikely(key))
5932 goto invalid_keyword;
5933 return 1;
5934 invalid_keyword_type:
5935 PyErr_Format(PyExc_TypeError,
5936 "%s() keywords must be strings", function_name);
5937 return 0;
5938 invalid_keyword:
5939 PyErr_Format(PyExc_TypeError,
5940 #if PY_MAJOR_VERSION < 3
5941 "%s() got an unexpected keyword argument '%s'",
5942 function_name, PyString_AsString(key));
5943 #else
5944 "%s() got an unexpected keyword argument '%U'",
5945 function_name, key);
5946 #endif
5947 return 0;
5948 }
5949 """)
5951 #------------------------------------------------------------------------------------
5952 #
5953 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5954 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5955 # keywords will raise an invalid keyword error.
5956 #
5957 # Three kinds of errors are checked: 1) non-string keywords, 2)
5958 # unexpected keywords and 3) overlap with positional arguments.
5959 #
5960 # If num_posargs is greater 0, it denotes the number of positional
5961 # arguments that were passed and that must therefore not appear
5962 # amongst the keywords as well.
5963 #
5964 # This method does not check for required keyword arguments.
5965 #
5967 parse_keywords_utility_code = UtilityCode(
5968 proto = """
5969 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5970 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5971 const char* function_name); /*proto*/
5972 """,
5973 impl = """
5974 static int __Pyx_ParseOptionalKeywords(
5975 PyObject *kwds,
5976 PyObject **argnames[],
5977 PyObject *kwds2,
5978 PyObject *values[],
5979 Py_ssize_t num_pos_args,
5980 const char* function_name)
5981 {
5982 PyObject *key = 0, *value = 0;
5983 Py_ssize_t pos = 0;
5984 PyObject*** name;
5985 PyObject*** first_kw_arg = argnames + num_pos_args;
5987 while (PyDict_Next(kwds, &pos, &key, &value)) {
5988 name = first_kw_arg;
5989 while (*name && (**name != key)) name++;
5990 if (*name) {
5991 values[name-argnames] = value;
5992 } else {
5993 #if PY_MAJOR_VERSION < 3
5994 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5995 #else
5996 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5997 #endif
5998 goto invalid_keyword_type;
5999 } else {
6000 for (name = first_kw_arg; *name; name++) {
6001 #if PY_MAJOR_VERSION >= 3
6002 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
6003 PyUnicode_Compare(**name, key) == 0) break;
6004 #else
6005 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
6006 _PyString_Eq(**name, key)) break;
6007 #endif
6008 }
6009 if (*name) {
6010 values[name-argnames] = value;
6011 } else {
6012 /* unexpected keyword found */
6013 for (name=argnames; name != first_kw_arg; name++) {
6014 if (**name == key) goto arg_passed_twice;
6015 #if PY_MAJOR_VERSION >= 3
6016 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
6017 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
6018 #else
6019 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
6020 _PyString_Eq(**name, key)) goto arg_passed_twice;
6021 #endif
6022 }
6023 if (kwds2) {
6024 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
6025 } else {
6026 goto invalid_keyword;
6027 }
6028 }
6029 }
6030 }
6031 }
6032 return 0;
6033 arg_passed_twice:
6034 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
6035 goto bad;
6036 invalid_keyword_type:
6037 PyErr_Format(PyExc_TypeError,
6038 "%s() keywords must be strings", function_name);
6039 goto bad;
6040 invalid_keyword:
6041 PyErr_Format(PyExc_TypeError,
6042 #if PY_MAJOR_VERSION < 3
6043 "%s() got an unexpected keyword argument '%s'",
6044 function_name, PyString_AsString(key));
6045 #else
6046 "%s() got an unexpected keyword argument '%U'",
6047 function_name, key);
6048 #endif
6049 bad:
6050 return -1;
6051 }
6052 """)
6054 #------------------------------------------------------------------------------------
6056 traceback_utility_code = UtilityCode(
6057 proto = """
6058 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
6059 """,
6060 impl = """
6061 #include "compile.h"
6062 #include "frameobject.h"
6063 #include "traceback.h"
6065 static void __Pyx_AddTraceback(const char *funcname) {
6066 PyObject *py_srcfile = 0;
6067 PyObject *py_funcname = 0;
6068 PyObject *py_globals = 0;
6069 PyCodeObject *py_code = 0;
6070 PyFrameObject *py_frame = 0;
6072 #if PY_MAJOR_VERSION < 3
6073 py_srcfile = PyString_FromString(%(FILENAME)s);
6074 #else
6075 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
6076 #endif
6077 if (!py_srcfile) goto bad;
6078 if (%(CLINENO)s) {
6079 #if PY_MAJOR_VERSION < 3
6080 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
6081 #else
6082 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
6083 #endif
6084 }
6085 else {
6086 #if PY_MAJOR_VERSION < 3
6087 py_funcname = PyString_FromString(funcname);
6088 #else
6089 py_funcname = PyUnicode_FromString(funcname);
6090 #endif
6091 }
6092 if (!py_funcname) goto bad;
6093 py_globals = PyModule_GetDict(%(GLOBALS)s);
6094 if (!py_globals) goto bad;
6095 py_code = PyCode_New(
6096 0, /*int argcount,*/
6097 #if PY_MAJOR_VERSION >= 3
6098 0, /*int kwonlyargcount,*/
6099 #endif
6100 0, /*int nlocals,*/
6101 0, /*int stacksize,*/
6102 0, /*int flags,*/
6103 %(EMPTY_BYTES)s, /*PyObject *code,*/
6104 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6105 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6106 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6107 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6108 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6109 py_srcfile, /*PyObject *filename,*/
6110 py_funcname, /*PyObject *name,*/
6111 %(LINENO)s, /*int firstlineno,*/
6112 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6113 );
6114 if (!py_code) goto bad;
6115 py_frame = PyFrame_New(
6116 PyThreadState_GET(), /*PyThreadState *tstate,*/
6117 py_code, /*PyCodeObject *code,*/
6118 py_globals, /*PyObject *globals,*/
6119 0 /*PyObject *locals*/
6120 );
6121 if (!py_frame) goto bad;
6122 py_frame->f_lineno = %(LINENO)s;
6123 PyTraceBack_Here(py_frame);
6124 bad:
6125 Py_XDECREF(py_srcfile);
6126 Py_XDECREF(py_funcname);
6127 Py_XDECREF(py_code);
6128 Py_XDECREF(py_frame);
6129 }
6130 """ % {
6131 'FILENAME': Naming.filename_cname,
6132 'LINENO': Naming.lineno_cname,
6133 'CFILENAME': Naming.cfilenm_cname,
6134 'CLINENO': Naming.clineno_cname,
6135 'GLOBALS': Naming.module_cname,
6136 'EMPTY_TUPLE' : Naming.empty_tuple,
6137 'EMPTY_BYTES' : Naming.empty_bytes,
6138 })
6140 #------------------------------------------------------------------------------------
6142 unraisable_exception_utility_code = UtilityCode(
6143 proto = """
6144 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
6145 """,
6146 impl = """
6147 static void __Pyx_WriteUnraisable(const char *name) {
6148 PyObject *old_exc, *old_val, *old_tb;
6149 PyObject *ctx;
6150 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
6151 #if PY_MAJOR_VERSION < 3
6152 ctx = PyString_FromString(name);
6153 #else
6154 ctx = PyUnicode_FromString(name);
6155 #endif
6156 __Pyx_ErrRestore(old_exc, old_val, old_tb);
6157 if (!ctx) {
6158 PyErr_WriteUnraisable(Py_None);
6159 } else {
6160 PyErr_WriteUnraisable(ctx);
6161 Py_DECREF(ctx);
6162 }
6163 }
6164 """,
6165 requires=[restore_exception_utility_code])
6167 #------------------------------------------------------------------------------------
6169 set_vtable_utility_code = UtilityCode(
6170 proto = """
6171 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
6172 """,
6173 impl = """
6174 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
6175 #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
6176 PyObject *ob = PyCapsule_New(vtable, 0, 0);
6177 #else
6178 PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
6179 #endif
6180 if (!ob)
6181 goto bad;
6182 if (PyDict_SetItemString(dict, "__pyx_vtable__", ob) < 0)
6183 goto bad;
6184 Py_DECREF(ob);
6185 return 0;
6186 bad:
6187 Py_XDECREF(ob);
6188 return -1;
6189 }
6190 """)
6192 #------------------------------------------------------------------------------------
6194 get_vtable_utility_code = UtilityCode(
6195 proto = """
6196 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
6197 """,
6198 impl = r"""
6199 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
6200 PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
6201 if (!ob)
6202 goto bad;
6203 #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
6204 *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
6205 #else
6206 *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
6207 #endif
6208 if (!*(void **)vtabptr)
6209 goto bad;
6210 Py_DECREF(ob);
6211 return 0;
6212 bad:
6213 Py_XDECREF(ob);
6214 return -1;
6215 }
6216 """)
6218 #------------------------------------------------------------------------------------
6220 init_string_tab_utility_code = UtilityCode(
6221 proto = """
6222 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
6223 """,
6224 impl = """
6225 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
6226 while (t->p) {
6227 #if PY_MAJOR_VERSION < 3
6228 if (t->is_unicode) {
6229 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
6230 } else if (t->intern) {
6231 *t->p = PyString_InternFromString(t->s);
6232 } else {
6233 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
6234 }
6235 #else /* Python 3+ has unicode identifiers */
6236 if (t->is_unicode | t->is_str) {
6237 if (t->intern) {
6238 *t->p = PyUnicode_InternFromString(t->s);
6239 } else if (t->encoding) {
6240 *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
6241 } else {
6242 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
6243 }
6244 } else {
6245 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
6246 }
6247 #endif
6248 if (!*t->p)
6249 return -1;
6250 ++t;
6251 }
6252 return 0;
6253 }
6254 """)
6256 #------------------------------------------------------------------------------------
6258 force_init_threads_utility_code = UtilityCode(
6259 proto="""
6260 #ifndef __PYX_FORCE_INIT_THREADS
6261 #if PY_VERSION_HEX < 0x02040200
6262 #define __PYX_FORCE_INIT_THREADS 1
6263 #else
6264 #define __PYX_FORCE_INIT_THREADS 0
6265 #endif
6266 #endif
6267 """)
6269 #------------------------------------------------------------------------------------
6271 # Note that cPython ignores PyTrace_EXCEPTION,
6272 # but maybe some other profilers don't.
6274 profile_utility_code = UtilityCode(proto="""
6275 #ifndef CYTHON_PROFILE
6276 #define CYTHON_PROFILE 1
6277 #endif
6279 #ifndef CYTHON_PROFILE_REUSE_FRAME
6280 #define CYTHON_PROFILE_REUSE_FRAME 0
6281 #endif
6283 #if CYTHON_PROFILE
6285 #include "compile.h"
6286 #include "frameobject.h"
6287 #include "traceback.h"
6289 #if CYTHON_PROFILE_REUSE_FRAME
6290 #define CYTHON_FRAME_MODIFIER static
6291 #define CYTHON_FRAME_DEL
6292 #else
6293 #define CYTHON_FRAME_MODIFIER
6294 #define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
6295 #endif
6297 #define __Pyx_TraceDeclarations \\
6298 static PyCodeObject *%(FRAME_CODE)s = NULL; \\
6299 CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
6300 int __Pyx_use_tracing = 0;
6302 #define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
6303 if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) { \\
6304 __Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
6305 }
6307 #define __Pyx_TraceException() \\
6308 if (unlikely(__Pyx_use_tracing( && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6309 PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
6310 if (exc_info) { \\
6311 PyThreadState_GET()->c_profilefunc( \\
6312 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
6313 Py_DECREF(exc_info); \\
6314 } \\
6315 }
6317 #define __Pyx_TraceReturn(result) \\
6318 if (unlikely(__Pyx_use_tracing) && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
6319 PyThreadState_GET()->c_profilefunc( \\
6320 PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
6321 CYTHON_FRAME_DEL; \\
6322 }
6324 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6325 static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
6327 #else
6329 #define __Pyx_TraceDeclarations
6330 #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
6331 #define __Pyx_TraceException()
6332 #define __Pyx_TraceReturn(result)
6334 #endif /* CYTHON_PROFILE */
6335 """
6336 % {
6337 "FRAME": Naming.frame_cname,
6338 "FRAME_CODE": Naming.frame_code_cname,
6339 },
6340 impl = """
6342 #if CYTHON_PROFILE
6344 static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
6345 PyFrameObject** frame,
6346 const char *funcname,
6347 const char *srcfile,
6348 int firstlineno) {
6349 if (*frame == NULL || !CYTHON_PROFILE_REUSE_FRAME) {
6350 if (*code == NULL) {
6351 *code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
6352 if (*code == NULL) return 0;
6353 }
6354 *frame = PyFrame_New(
6355 PyThreadState_GET(), /*PyThreadState *tstate*/
6356 *code, /*PyCodeObject *code*/
6357 PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
6358 0 /*PyObject *locals*/
6359 );
6360 if (*frame == NULL) return 0;
6361 }
6362 else {
6363 (*frame)->f_tstate = PyThreadState_GET();
6364 }
6365 return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
6366 }
6368 static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
6369 PyObject *py_srcfile = 0;
6370 PyObject *py_funcname = 0;
6371 PyCodeObject *py_code = 0;
6373 #if PY_MAJOR_VERSION < 3
6374 py_funcname = PyString_FromString(funcname);
6375 py_srcfile = PyString_FromString(srcfile);
6376 #else
6377 py_funcname = PyUnicode_FromString(funcname);
6378 py_srcfile = PyUnicode_FromString(srcfile);
6379 #endif
6380 if (!py_funcname | !py_srcfile) goto bad;
6382 py_code = PyCode_New(
6383 0, /*int argcount,*/
6384 #if PY_MAJOR_VERSION >= 3
6385 0, /*int kwonlyargcount,*/
6386 #endif
6387 0, /*int nlocals,*/
6388 0, /*int stacksize,*/
6389 0, /*int flags,*/
6390 %(EMPTY_BYTES)s, /*PyObject *code,*/
6391 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
6392 %(EMPTY_TUPLE)s, /*PyObject *names,*/
6393 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
6394 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
6395 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
6396 py_srcfile, /*PyObject *filename,*/
6397 py_funcname, /*PyObject *name,*/
6398 firstlineno, /*int firstlineno,*/
6399 %(EMPTY_BYTES)s /*PyObject *lnotab*/
6400 );
6402 bad:
6403 Py_XDECREF(py_srcfile);
6404 Py_XDECREF(py_funcname);
6406 return py_code;
6407 }
6409 #endif /* CYTHON_PROFILE */
6410 """ % {
6411 'EMPTY_TUPLE' : Naming.empty_tuple,
6412 'EMPTY_BYTES' : Naming.empty_bytes,
6413 "MODULE": Naming.module_cname,
6414 })
