Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 2299:a3ad25325fe4
fix __future__ division semantics for constant expressions and C integers
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Wed Jul 08 21:13:14 2009 +0200 (2 years ago) |
| parents | 67a370779b96 |
| children | 3b63953d39b9 |
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import sys, os, time, copy
7 import Code
8 import Builtin
9 from Errors import error, warning, InternalError
10 import Naming
11 import PyrexTypes
12 import TypeSlots
13 from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
14 from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
15 StructOrUnionScope, PyClassScope, CClassScope
16 from Cython.Utils import open_new_file, replace_suffix
17 from Code import UtilityCode
18 from StringEncoding import EncodedString, escape_byte_string, split_docstring
19 import Options
20 import ControlFlow
21 import DebugFlags
23 absolute_path_length = 0
25 def relative_position(pos):
26 """
27 We embed the relative filename in the generated C file, since we
28 don't want to have to regnerate and compile all the source code
29 whenever the Python install directory moves (which could happen,
30 e.g,. when distributing binaries.)
32 INPUT:
33 a position tuple -- (absolute filename, line number column position)
35 OUTPUT:
36 relative filename
37 line number
39 AUTHOR: William Stein
40 """
41 global absolute_path_length
42 if absolute_path_length==0:
43 absolute_path_length = len(os.path.abspath(os.getcwd()))
44 return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
46 def embed_position(pos, docstring):
47 if not Options.embed_pos_in_docstring:
48 return docstring
49 pos_line = u'File: %s (starting at line %s)' % relative_position(pos)
50 if docstring is None:
51 # unicode string
52 return EncodedString(pos_line)
54 # make sure we can encode the filename in the docstring encoding
55 # otherwise make the docstring a unicode string
56 encoding = docstring.encoding
57 if encoding is not None:
58 try:
59 encoded_bytes = pos_line.encode(encoding)
60 except UnicodeEncodeError:
61 encoding = None
63 if not docstring:
64 # reuse the string encoding of the original docstring
65 doc = EncodedString(pos_line)
66 else:
67 doc = EncodedString(pos_line + u'\n' + docstring)
68 doc.encoding = encoding
69 return doc
72 from Code import CCodeWriter
73 from types import FunctionType
75 def write_func_call(func):
76 def f(*args, **kwds):
77 if len(args) > 1 and isinstance(args[1], CCodeWriter):
78 # here we annotate the code with this function call
79 # but only if new code is generated
80 node, code = args[:2]
81 marker = ' /* %s -> %s.%s %s */' % (
82 ' ' * code.call_level,
83 node.__class__.__name__,
84 func.__name__,
85 node.pos[1:])
86 pristine = code.buffer.stream.tell()
87 code.putln(marker)
88 start = code.buffer.stream.tell()
89 code.call_level += 4
90 res = func(*args, **kwds)
91 code.call_level -= 4
92 if start == code.buffer.stream.tell():
93 code.buffer.stream.seek(pristine)
94 else:
95 marker = marker.replace('->', '<-')
96 code.putln(marker)
97 return res
98 else:
99 return func(*args, **kwds)
100 return f
102 class VerboseCodeWriter(type):
103 # Set this as a metaclass to trace function calls in code.
104 # This slows down code generation and makes much larger files.
105 def __new__(cls, name, bases, attrs):
106 attrs = dict(attrs)
107 for mname, m in attrs.items():
108 if isinstance(m, FunctionType):
109 attrs[mname] = write_func_call(m)
110 return super(VerboseCodeWriter, cls).__new__(cls, name, bases, attrs)
113 class Node(object):
114 # pos (string, int, int) Source file position
115 # is_name boolean Is a NameNode
116 # is_literal boolean Is a ConstNode
118 if DebugFlags.debug_trace_code_generation:
119 __metaclass__ = VerboseCodeWriter
121 is_name = 0
122 is_literal = 0
123 temps = None
125 # All descandants should set child_attrs to a list of the attributes
126 # containing nodes considered "children" in the tree. Each such attribute
127 # can either contain a single node or a list of nodes. See Visitor.py.
128 child_attrs = None
130 def __init__(self, pos, **kw):
131 self.pos = pos
132 self.__dict__.update(kw)
134 gil_message = "Operation"
136 nogil_check = None
138 def gil_error(self, env=None):
139 error(self.pos, "%s not allowed without gil" % self.gil_message)
141 def clone_node(self):
142 """Clone the node. This is defined as a shallow copy, except for member lists
143 amongst the child attributes (from get_child_accessors) which are also
144 copied. Lists containing child nodes are thus seen as a way for the node
145 to hold multiple children directly; the list is not treated as a seperate
146 level in the tree."""
147 result = copy.copy(self)
148 for attrname in result.child_attrs:
149 value = getattr(result, attrname)
150 if isinstance(value, list):
151 setattr(result, attrname, [x for x in value])
152 return result
155 #
156 # There are 4 phases of parse tree processing, applied in order to
157 # all the statements in a given scope-block:
158 #
159 # (0) analyse_control_flow
160 # Create the control flow tree into which state can be asserted and
161 # queried.
162 #
163 # (1) analyse_declarations
164 # Make symbol table entries for all declarations at the current
165 # level, both explicit (def, cdef, etc.) and implicit (assignment
166 # to an otherwise undeclared name).
167 #
168 # (2) analyse_expressions
169 # Determine the result types of expressions and fill in the
170 # 'type' attribute of each ExprNode. Insert coercion nodes into the
171 # tree where needed to convert to and from Python objects.
172 # Allocate temporary locals for intermediate results. Fill
173 # in the 'result_code' attribute of each ExprNode with a C code
174 # fragment.
175 #
176 # (3) generate_code
177 # Emit C code for all declarations, statements and expressions.
178 # Recursively applies the 3 processing phases to the bodies of
179 # functions.
180 #
182 def analyse_control_flow(self, env):
183 pass
185 def analyse_declarations(self, env):
186 pass
188 def analyse_expressions(self, env):
189 raise InternalError("analyse_expressions not implemented for %s" % \
190 self.__class__.__name__)
192 def generate_code(self, code):
193 raise InternalError("generate_code not implemented for %s" % \
194 self.__class__.__name__)
196 def annotate(self, code):
197 # mro does the wrong thing
198 if isinstance(self, BlockNode):
199 self.body.annotate(code)
201 def end_pos(self):
202 try:
203 return self._end_pos
204 except AttributeError:
205 pos = self.pos
206 if not self.child_attrs:
207 self._end_pos = pos
208 return pos
209 for attr in self.child_attrs:
210 child = getattr(self, attr)
211 # Sometimes lists, sometimes nodes
212 if child is None:
213 pass
214 elif isinstance(child, list):
215 for c in child:
216 pos = max(pos, c.end_pos())
217 else:
218 pos = max(pos, child.end_pos())
219 self._end_pos = pos
220 return pos
222 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
223 if cutoff == 0:
224 return "<...nesting level cutoff...>"
225 if encountered is None:
226 encountered = set()
227 if id(self) in encountered:
228 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
229 encountered.add(id(self))
231 def dump_child(x, level):
232 if isinstance(x, Node):
233 return x.dump(level, filter_out, cutoff-1, encountered)
234 elif isinstance(x, list):
235 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
236 else:
237 return repr(x)
240 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
241 if len(attrs) == 0:
242 return "<%s (%d)>" % (self.__class__.__name__, id(self))
243 else:
244 indent = " " * level
245 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
246 for key, value in attrs:
247 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
248 res += "%s>" % indent
249 return res
251 class CompilerDirectivesNode(Node):
252 """
253 Sets compiler directives for the children nodes
254 """
255 # directives {string:value} A dictionary holding the right value for
256 # *all* possible directives.
257 # body Node
258 child_attrs = ["body"]
260 def analyse_control_flow(self, env):
261 old = env.directives
262 env.directives = self.directives
263 self.body.analyse_control_flow(env)
264 env.directives = old
266 def analyse_declarations(self, env):
267 old = env.directives
268 env.directives = self.directives
269 self.body.analyse_declarations(env)
270 env.directives = old
272 def analyse_expressions(self, env):
273 old = env.directives
274 env.directives = self.directives
275 self.body.analyse_expressions(env)
276 env.directives = old
278 def generate_function_definitions(self, env, code):
279 env_old = env.directives
280 code_old = code.globalstate.directives
281 code.globalstate.directives = self.directives
282 self.body.generate_function_definitions(env, code)
283 env.directives = env_old
284 code.globalstate.directives = code_old
286 def generate_execution_code(self, code):
287 old = code.globalstate.directives
288 code.globalstate.directives = self.directives
289 self.body.generate_execution_code(code)
290 code.globalstate.directives = old
292 def annotate(self, code):
293 old = code.globalstate.directives
294 code.globalstate.directives = self.directives
295 self.body.annotate(code)
296 code.globalstate.directives = old
298 class BlockNode(object):
299 # Mixin class for nodes representing a declaration block.
301 def generate_cached_builtins_decls(self, env, code):
302 entries = env.global_scope().undeclared_cached_builtins
303 for entry in entries:
304 code.globalstate.add_cached_builtin_decl(entry)
305 del entries[:]
308 class StatListNode(Node):
309 # stats a list of StatNode
311 child_attrs = ["stats"]
313 def create_analysed(pos, env, *args, **kw):
314 node = StatListNode(pos, *args, **kw)
315 return node # No node-specific analysis necesarry
316 create_analysed = staticmethod(create_analysed)
318 def analyse_control_flow(self, env):
319 for stat in self.stats:
320 stat.analyse_control_flow(env)
322 def analyse_declarations(self, env):
323 #print "StatListNode.analyse_declarations" ###
324 for stat in self.stats:
325 stat.analyse_declarations(env)
327 def analyse_expressions(self, env):
328 #print "StatListNode.analyse_expressions" ###
329 for stat in self.stats:
330 stat.analyse_expressions(env)
332 def generate_function_definitions(self, env, code):
333 #print "StatListNode.generate_function_definitions" ###
334 for stat in self.stats:
335 stat.generate_function_definitions(env, code)
337 def generate_execution_code(self, code):
338 #print "StatListNode.generate_execution_code" ###
339 for stat in self.stats:
340 code.mark_pos(stat.pos)
341 stat.generate_execution_code(code)
343 def annotate(self, code):
344 for stat in self.stats:
345 stat.annotate(code)
348 class StatNode(Node):
349 #
350 # Code generation for statements is split into the following subphases:
351 #
352 # (1) generate_function_definitions
353 # Emit C code for the definitions of any structs,
354 # unions, enums and functions defined in the current
355 # scope-block.
356 #
357 # (2) generate_execution_code
358 # Emit C code for executable statements.
359 #
361 def generate_function_definitions(self, env, code):
362 pass
364 def generate_execution_code(self, code):
365 raise InternalError("generate_execution_code not implemented for %s" % \
366 self.__class__.__name__)
369 class CDefExternNode(StatNode):
370 # include_file string or None
371 # body StatNode
373 child_attrs = ["body"]
375 def analyse_declarations(self, env):
376 if self.include_file:
377 env.add_include_file(self.include_file)
378 old_cinclude_flag = env.in_cinclude
379 env.in_cinclude = 1
380 self.body.analyse_declarations(env)
381 env.in_cinclude = old_cinclude_flag
383 def analyse_expressions(self, env):
384 pass
386 def generate_execution_code(self, code):
387 pass
389 def annotate(self, code):
390 self.body.annotate(code)
393 class CDeclaratorNode(Node):
394 # Part of a C declaration.
395 #
396 # Processing during analyse_declarations phase:
397 #
398 # analyse
399 # Returns (name, type) pair where name is the
400 # CNameDeclaratorNode of the name being declared
401 # and type is the type it is being declared as.
402 #
403 # calling_convention string Calling convention of CFuncDeclaratorNode
404 # for which this is a base
406 child_attrs = []
408 calling_convention = ""
411 class CNameDeclaratorNode(CDeclaratorNode):
412 # name string The Pyrex name being declared
413 # cname string or None C name, if specified
414 # default ExprNode or None the value assigned on declaration
416 child_attrs = ['default']
418 default = None
420 def analyse(self, base_type, env, nonempty = 0):
421 if nonempty and self.name == '':
422 # May have mistaken the name for the type.
423 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
424 error(self.pos, "Missing argument name")
425 elif base_type.is_void:
426 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
427 else:
428 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
429 base_type = py_object_type
430 self.type = base_type
431 return self, base_type
433 class CPtrDeclaratorNode(CDeclaratorNode):
434 # base CDeclaratorNode
436 child_attrs = ["base"]
438 def analyse(self, base_type, env, nonempty = 0):
439 if base_type.is_pyobject:
440 error(self.pos,
441 "Pointer base type cannot be a Python object")
442 ptr_type = PyrexTypes.c_ptr_type(base_type)
443 return self.base.analyse(ptr_type, env, nonempty = nonempty)
445 class CArrayDeclaratorNode(CDeclaratorNode):
446 # base CDeclaratorNode
447 # dimension ExprNode
449 child_attrs = ["base", "dimension"]
451 def analyse(self, base_type, env, nonempty = 0):
452 if self.dimension:
453 self.dimension.analyse_const_expression(env)
454 if not self.dimension.type.is_int:
455 error(self.dimension.pos, "Array dimension not integer")
456 size = self.dimension.get_constant_c_result_code()
457 if size is not None:
458 try:
459 size = int(size)
460 except ValueError:
461 # runtime constant?
462 pass
463 else:
464 size = None
465 if not base_type.is_complete():
466 error(self.pos,
467 "Array element type '%s' is incomplete" % base_type)
468 if base_type.is_pyobject:
469 error(self.pos,
470 "Array element cannot be a Python object")
471 if base_type.is_cfunction:
472 error(self.pos,
473 "Array element cannot be a function")
474 array_type = PyrexTypes.c_array_type(base_type, size)
475 return self.base.analyse(array_type, env, nonempty = nonempty)
478 class CFuncDeclaratorNode(CDeclaratorNode):
479 # base CDeclaratorNode
480 # args [CArgDeclNode]
481 # has_varargs boolean
482 # exception_value ConstNode
483 # exception_check boolean True if PyErr_Occurred check needed
484 # nogil boolean Can be called without gil
485 # with_gil boolean Acquire gil around function body
487 child_attrs = ["base", "args", "exception_value"]
489 overridable = 0
490 optional_arg_count = 0
492 def analyse(self, return_type, env, nonempty = 0):
493 if nonempty:
494 nonempty -= 1
495 func_type_args = []
496 for arg_node in self.args:
497 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
498 name = name_declarator.name
499 if name_declarator.cname:
500 error(self.pos,
501 "Function argument cannot have C name specification")
502 # Turn *[] argument into **
503 if type.is_array:
504 type = PyrexTypes.c_ptr_type(type.base_type)
505 # Catch attempted C-style func(void) decl
506 if type.is_void:
507 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
508 func_type_args.append(
509 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
510 if arg_node.default:
511 self.optional_arg_count += 1
512 elif self.optional_arg_count:
513 error(self.pos, "Non-default argument follows default argument")
515 if self.optional_arg_count:
516 scope = StructOrUnionScope()
517 arg_count_member = '%sn' % Naming.pyrex_prefix
518 scope.declare_var(arg_count_member, PyrexTypes.c_int_type, self.pos)
519 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
520 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
521 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
522 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
523 kind = 'struct',
524 scope = scope,
525 typedef_flag = 0,
526 pos = self.pos,
527 cname = struct_cname)
528 self.op_args_struct.defined_in_pxd = 1
529 self.op_args_struct.used = 1
531 exc_val = None
532 exc_check = 0
533 if self.exception_check == '+':
534 env.add_include_file('stdexcept')
535 if return_type.is_pyobject \
536 and (self.exception_value or self.exception_check) \
537 and self.exception_check != '+':
538 error(self.pos,
539 "Exception clause not allowed for function returning Python object")
540 else:
541 if self.exception_value:
542 self.exception_value.analyse_const_expression(env)
543 exc_val = self.exception_value.get_constant_c_result_code()
544 if self.exception_check == '+':
545 exc_val_type = self.exception_value.type
546 if not exc_val_type.is_error and \
547 not exc_val_type.is_pyobject and \
548 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
549 error(self.exception_value.pos,
550 "Exception value must be a Python exception or cdef function with no arguments.")
551 else:
552 if not return_type.assignable_from(self.exception_value.type):
553 error(self.exception_value.pos,
554 "Exception value incompatible with function return type")
555 exc_check = self.exception_check
556 if return_type.is_array:
557 error(self.pos,
558 "Function cannot return an array")
559 if return_type.is_cfunction:
560 error(self.pos,
561 "Function cannot return a function")
562 func_type = PyrexTypes.CFuncType(
563 return_type, func_type_args, self.has_varargs,
564 optional_arg_count = self.optional_arg_count,
565 exception_value = exc_val, exception_check = exc_check,
566 calling_convention = self.base.calling_convention,
567 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
568 if self.optional_arg_count:
569 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
570 callspec = env.directives['callspec']
571 if callspec:
572 current = func_type.calling_convention
573 if current and current != callspec:
574 error(self.pos, "cannot have both '%s' and '%s' "
575 "calling conventions" % (current, callspec))
576 func_type.calling_convention = callspec
577 return self.base.analyse(func_type, env)
580 class CArgDeclNode(Node):
581 # Item in a function declaration argument list.
582 #
583 # base_type CBaseTypeNode
584 # declarator CDeclaratorNode
585 # not_none boolean Tagged with 'not None'
586 # default ExprNode or None
587 # default_value PyObjectConst constant for default value
588 # is_self_arg boolean Is the "self" arg of an extension type method
589 # is_kw_only boolean Is a keyword-only argument
591 child_attrs = ["base_type", "declarator", "default"]
593 is_self_arg = 0
594 is_generic = 1
595 type = None
596 name_declarator = None
597 default_value = None
599 def analyse(self, env, nonempty = 0):
600 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
601 if self.type is None:
602 # The parser may missinterpret names as types...
603 # We fix that here.
604 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
605 if nonempty:
606 self.declarator.name = self.base_type.name
607 self.base_type.name = None
608 self.base_type.is_basic_c_type = False
609 could_be_name = True
610 else:
611 could_be_name = False
612 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
613 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
614 self.declarator.name = self.base_type.arg_name
615 return self.declarator.analyse(base_type, env, nonempty = nonempty)
616 else:
617 return self.name_declarator, self.type
619 def calculate_default_value_code(self, code):
620 if self.default_value is None:
621 if self.default:
622 if self.default.is_literal:
623 # will not output any code, just assign the result_code
624 self.default.generate_evaluation_code(code)
625 return self.type.cast_code(self.default.result())
626 self.default_value = code.get_argument_default_const(self.type)
627 return self.default_value
629 def annotate(self, code):
630 if self.default:
631 self.default.annotate(code)
634 class CBaseTypeNode(Node):
635 # Abstract base class for C base type nodes.
636 #
637 # Processing during analyse_declarations phase:
638 #
639 # analyse
640 # Returns the type.
642 pass
644 class CAnalysedBaseTypeNode(Node):
645 # type type
647 child_attrs = []
649 def analyse(self, env, could_be_name = False):
650 return self.type
652 class CSimpleBaseTypeNode(CBaseTypeNode):
653 # name string
654 # module_path [string] Qualifying name components
655 # is_basic_c_type boolean
656 # signed boolean
657 # longness integer
658 # complex boolean
659 # is_self_arg boolean Is self argument of C method
661 child_attrs = []
662 arg_name = None # in case the argument name was interpreted as a type
664 def analyse(self, env, could_be_name = False):
665 # Return type descriptor.
666 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
667 type = None
668 if self.is_basic_c_type:
669 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
670 if not type:
671 error(self.pos, "Unrecognised type modifier combination")
672 elif self.name == "object" and not self.module_path:
673 type = py_object_type
674 elif self.name is None:
675 if self.is_self_arg and env.is_c_class_scope:
676 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
677 type = env.parent_type
678 else:
679 type = py_object_type
680 else:
681 if self.module_path:
682 scope = env.find_imported_module(self.module_path, self.pos)
683 else:
684 scope = env
685 if scope:
686 if scope.is_c_class_scope:
687 scope = scope.global_scope()
688 entry = scope.lookup(self.name)
689 if entry and entry.is_type:
690 type = entry.type
691 elif could_be_name:
692 if self.is_self_arg and env.is_c_class_scope:
693 type = env.parent_type
694 else:
695 type = py_object_type
696 self.arg_name = self.name
697 else:
698 error(self.pos, "'%s' is not a type identifier" % self.name)
699 if self.complex:
700 if not type.is_numeric or type.is_complex:
701 error(self.pos, "can only complexify c numeric types")
702 type = PyrexTypes.CComplexType(type)
703 type.create_declaration_utility_code(env)
704 if type:
705 return type
706 else:
707 return PyrexTypes.error_type
709 class CBufferAccessTypeNode(CBaseTypeNode):
710 # After parsing:
711 # positional_args [ExprNode] List of positional arguments
712 # keyword_args DictNode Keyword arguments
713 # base_type_node CBaseTypeNode
715 # After analysis:
716 # type PyrexType.BufferType ...containing the right options
719 child_attrs = ["base_type_node", "positional_args",
720 "keyword_args", "dtype_node"]
722 dtype_node = None
724 name = None
726 def analyse(self, env, could_be_name = False):
727 base_type = self.base_type_node.analyse(env)
728 if base_type.is_error: return base_type
729 import Buffer
731 options = Buffer.analyse_buffer_options(
732 self.pos,
733 env,
734 self.positional_args,
735 self.keyword_args,
736 base_type.buffer_defaults)
738 self.type = PyrexTypes.BufferType(base_type, **options)
739 return self.type
741 class CComplexBaseTypeNode(CBaseTypeNode):
742 # base_type CBaseTypeNode
743 # declarator CDeclaratorNode
745 child_attrs = ["base_type", "declarator"]
747 def analyse(self, env, could_be_name = False):
748 base = self.base_type.analyse(env, could_be_name)
749 _, type = self.declarator.analyse(base, env)
750 return type
753 class CVarDefNode(StatNode):
754 # C variable definition or forward/extern function declaration.
755 #
756 # visibility 'private' or 'public' or 'extern'
757 # base_type CBaseTypeNode
758 # declarators [CDeclaratorNode]
759 # in_pxd boolean
760 # api boolean
761 # need_properties [entry]
763 # decorators [cython.locals(...)] or None
764 # directive_locals { string : NameNode } locals defined by cython.locals(...)
766 child_attrs = ["base_type", "declarators"]
767 need_properties = ()
769 decorators = None
770 directive_locals = {}
772 def analyse_declarations(self, env, dest_scope = None):
773 if not dest_scope:
774 dest_scope = env
775 self.dest_scope = dest_scope
776 base_type = self.base_type.analyse(env)
778 # If the field is an external typedef, we cannot be sure about the type,
779 # so do conversion ourself rather than rely on the CPython mechanism (through
780 # a property; made in AnalyseDeclarationsTransform).
781 if (dest_scope.is_c_class_scope
782 and self.visibility == 'public'
783 and base_type.is_pyobject
784 and (base_type.is_builtin_type or base_type.is_extension_type)):
785 self.need_properties = []
786 need_property = True
787 visibility = 'private'
788 else:
789 need_property = False
790 visibility = self.visibility
792 for declarator in self.declarators:
793 name_declarator, type = declarator.analyse(base_type, env)
794 if not type.is_complete():
795 if not (self.visibility == 'extern' and type.is_array):
796 error(declarator.pos,
797 "Variable type '%s' is incomplete" % type)
798 if self.visibility == 'extern' and type.is_pyobject:
799 error(declarator.pos,
800 "Python object cannot be declared extern")
801 name = name_declarator.name
802 cname = name_declarator.cname
803 if name == '':
804 error(declarator.pos, "Missing name in declaration.")
805 return
806 if type.is_cfunction:
807 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
808 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
809 api = self.api)
810 if entry is not None:
811 entry.directive_locals = self.directive_locals
812 else:
813 if self.directive_locals:
814 s.error("Decorators can only be followed by functions")
815 if self.in_pxd and self.visibility != 'extern':
816 error(self.pos,
817 "Only 'extern' C variable declaration allowed in .pxd file")
818 entry = dest_scope.declare_var(name, type, declarator.pos,
819 cname = cname, visibility = visibility, is_cdef = 1)
820 if need_property:
821 self.need_properties.append(entry)
822 entry.needs_property = 1
825 class CStructOrUnionDefNode(StatNode):
826 # name string
827 # cname string or None
828 # kind "struct" or "union"
829 # typedef_flag boolean
830 # visibility "public" or "private"
831 # in_pxd boolean
832 # attributes [CVarDefNode] or None
833 # entry Entry
834 # packed boolean
836 child_attrs = ["attributes"]
838 def analyse_declarations(self, env):
839 scope = None
840 if self.visibility == 'extern' and self.packed:
841 error(self.pos, "Cannot declare extern struct as 'packed'")
842 if self.attributes is not None:
843 scope = StructOrUnionScope(self.name)
844 self.entry = env.declare_struct_or_union(
845 self.name, self.kind, scope, self.typedef_flag, self.pos,
846 self.cname, visibility = self.visibility, packed = self.packed)
847 if self.attributes is not None:
848 if self.in_pxd and not env.in_cinclude:
849 self.entry.defined_in_pxd = 1
850 for attr in self.attributes:
851 attr.analyse_declarations(env, scope)
852 if self.visibility != 'extern':
853 need_typedef_indirection = False
854 for attr in scope.var_entries:
855 type = attr.type
856 while type.is_array:
857 type = type.base_type
858 if type == self.entry.type:
859 error(attr.pos, "Struct cannot contain itself as a member.")
860 if self.typedef_flag:
861 while type.is_ptr:
862 type = type.base_type
863 if type == self.entry.type:
864 need_typedef_indirection = True
865 if need_typedef_indirection:
866 # C can't handle typedef structs that refer to themselves.
867 struct_entry = self.entry
868 self.entry = env.declare_typedef(
869 self.name, struct_entry.type, self.pos,
870 cname = self.cname, visibility='ignore')
871 struct_entry.type.typedef_flag = False
872 # FIXME: this might be considered a hack ;-)
873 struct_entry.cname = struct_entry.type.cname = \
874 '_' + self.entry.type.typedef_cname
876 def analyse_expressions(self, env):
877 pass
879 def generate_execution_code(self, code):
880 pass
883 class CEnumDefNode(StatNode):
884 # name string or None
885 # cname string or None
886 # items [CEnumDefItemNode]
887 # typedef_flag boolean
888 # visibility "public" or "private"
889 # in_pxd boolean
890 # entry Entry
892 child_attrs = ["items"]
894 def analyse_declarations(self, env):
895 self.entry = env.declare_enum(self.name, self.pos,
896 cname = self.cname, typedef_flag = self.typedef_flag,
897 visibility = self.visibility)
898 if self.items is not None:
899 if self.in_pxd and not env.in_cinclude:
900 self.entry.defined_in_pxd = 1
901 for item in self.items:
902 item.analyse_declarations(env, self.entry)
904 def generate_execution_code(self, code):
905 if self.visibility == 'public':
906 temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
907 for item in self.entry.enum_values:
908 code.putln("%s = PyInt_FromLong(%s); %s" % (
909 temp,
910 item.cname,
911 code.error_goto_if_null(temp, item.pos)))
912 code.put_gotref(temp)
913 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
914 Naming.module_cname,
915 item.name,
916 temp,
917 code.error_goto(item.pos)))
918 code.put_decref_clear(temp, PyrexTypes.py_object_type)
919 code.funcstate.release_temp(temp)
922 class CEnumDefItemNode(StatNode):
923 # name string
924 # cname string or None
925 # value ExprNode or None
927 child_attrs = ["value"]
929 def analyse_declarations(self, env, enum_entry):
930 if self.value:
931 self.value.analyse_const_expression(env)
932 if not self.value.type.is_int:
933 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
934 self.value.analyse_const_expression(env)
935 entry = env.declare_const(self.name, enum_entry.type,
936 self.value, self.pos, cname = self.cname,
937 visibility = enum_entry.visibility)
938 enum_entry.enum_values.append(entry)
941 class CTypeDefNode(StatNode):
942 # base_type CBaseTypeNode
943 # declarator CDeclaratorNode
944 # visibility "public" or "private"
945 # in_pxd boolean
947 child_attrs = ["base_type", "declarator"]
949 def analyse_declarations(self, env):
950 base = self.base_type.analyse(env)
951 name_declarator, type = self.declarator.analyse(base, env)
952 name = name_declarator.name
953 cname = name_declarator.cname
954 entry = env.declare_typedef(name, type, self.pos,
955 cname = cname, visibility = self.visibility)
956 if self.in_pxd and not env.in_cinclude:
957 entry.defined_in_pxd = 1
959 def analyse_expressions(self, env):
960 pass
961 def generate_execution_code(self, code):
962 pass
965 class FuncDefNode(StatNode, BlockNode):
966 # Base class for function definition nodes.
967 #
968 # return_type PyrexType
969 # #filename string C name of filename string const
970 # entry Symtab.Entry
971 # needs_closure boolean Whether or not this function has inner functions/classes/yield
972 # directive_locals { string : NameNode } locals defined by cython.locals(...)
974 py_func = None
975 assmt = None
976 needs_closure = False
978 def analyse_default_values(self, env):
979 genv = env.global_scope()
980 for arg in self.args:
981 if arg.default:
982 if arg.is_generic:
983 arg.default.analyse_types(env)
984 arg.default = arg.default.coerce_to(arg.type, genv)
985 else:
986 error(arg.pos,
987 "This argument cannot have a default value")
988 arg.default = None
990 def need_gil_acquisition(self, lenv):
991 return 0
993 def create_local_scope(self, env):
994 genv = env
995 while env.is_py_class_scope or env.is_c_class_scope:
996 env = env.outer_scope
997 if self.needs_closure:
998 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
999 else:
1000 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
1001 lenv.return_type = self.return_type
1002 type = self.entry.type
1003 if type.is_cfunction:
1004 lenv.nogil = type.nogil and not type.with_gil
1005 self.local_scope = lenv
1006 lenv.directives = env.directives
1007 return lenv
1009 def generate_function_definitions(self, env, code):
1010 import Buffer
1012 lenv = self.local_scope
1014 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
1015 self.entry.scope.is_c_class_scope)
1017 # Generate C code for header and body of function
1018 code.enter_cfunc_scope()
1019 code.return_from_error_cleanup_label = code.new_label()
1021 # ----- Top-level constants used by this function
1022 code.mark_pos(self.pos)
1023 self.generate_cached_builtins_decls(lenv, code)
1024 # ----- Function header
1025 code.putln("")
1026 if self.py_func:
1027 self.py_func.generate_function_header(code,
1028 with_pymethdef = env.is_py_class_scope,
1029 proto_only=True)
1030 self.generate_function_header(code,
1031 with_pymethdef = env.is_py_class_scope)
1032 # ----- Local variable declarations
1033 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1034 self.generate_argument_declarations(lenv, code)
1035 if self.needs_closure:
1036 code.putln("/* TODO: declare and create scope object */")
1037 code.put_var_declarations(lenv.var_entries)
1038 init = ""
1039 if not self.return_type.is_void:
1040 if self.return_type.is_pyobject:
1041 init = " = NULL"
1042 code.putln(
1043 "%s%s;" %
1044 (self.return_type.declaration_code(
1045 Naming.retval_cname),
1046 init))
1047 tempvardecl_code = code.insertion_point()
1048 self.generate_keyword_list(code)
1049 # ----- Extern library function declarations
1050 lenv.generate_library_function_declarations(code)
1051 # ----- GIL acquisition
1052 acquire_gil = self.need_gil_acquisition(lenv)
1053 if acquire_gil:
1054 env.use_utility_code(force_init_threads_utility_code)
1055 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1056 # ----- Automatic lead-ins for certain special functions
1057 if not lenv.nogil:
1058 code.put_setup_refcount_context(self.entry.name)
1059 if is_getbuffer_slot:
1060 self.getbuffer_init(code)
1061 # ----- Fetch arguments
1062 self.generate_argument_parsing_code(env, code)
1063 # If an argument is assigned to in the body, we must
1064 # incref it to properly keep track of refcounts.
1065 for entry in lenv.arg_entries:
1066 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1067 code.put_var_incref(entry)
1068 # ----- Initialise local variables
1069 for entry in lenv.var_entries:
1070 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1071 code.put_init_var_to_py_none(entry)
1072 # ----- Initialise local buffer auxiliary variables
1073 for entry in lenv.var_entries + lenv.arg_entries:
1074 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1075 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1076 # ----- Check and convert arguments
1077 self.generate_argument_type_tests(code)
1078 # ----- Acquire buffer arguments
1079 for entry in lenv.arg_entries:
1080 if entry.type.is_buffer:
1081 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1082 # ----- Function body
1083 self.body.generate_execution_code(code)
1084 # ----- Default return value
1085 code.putln("")
1086 if self.return_type.is_pyobject:
1087 #if self.return_type.is_extension_type:
1088 # lhs = "(PyObject *)%s" % Naming.retval_cname
1089 #else:
1090 lhs = Naming.retval_cname
1091 code.put_init_to_py_none(lhs, self.return_type)
1092 else:
1093 val = self.return_type.default_value
1094 if val:
1095 code.putln("%s = %s;" % (Naming.retval_cname, val))
1096 # ----- Error cleanup
1097 if code.error_label in code.labels_used:
1098 code.put_goto(code.return_label)
1099 code.put_label(code.error_label)
1100 for cname, type in code.funcstate.all_managed_temps():
1101 code.put_xdecref(cname, type)
1103 # Clean up buffers -- this calls a Python function
1104 # so need to save and restore error state
1105 buffers_present = len(lenv.buffer_entries) > 0
1106 if buffers_present:
1107 code.globalstate.use_utility_code(restore_exception_utility_code)
1108 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1109 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1110 for entry in lenv.buffer_entries:
1111 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1112 #code.putln("%s = 0;" % entry.cname)
1113 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1115 err_val = self.error_value()
1116 exc_check = self.caller_will_check_exceptions()
1117 if err_val is not None or exc_check:
1118 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1119 else:
1120 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1121 % self.entry.qualified_name, 0)
1122 code.putln(
1123 '__Pyx_WriteUnraisable("%s");' %
1124 self.entry.qualified_name)
1125 env.use_utility_code(unraisable_exception_utility_code)
1126 env.use_utility_code(restore_exception_utility_code)
1127 default_retval = self.return_type.default_value
1128 if err_val is None and default_retval:
1129 err_val = default_retval
1130 if err_val is not None:
1131 code.putln(
1132 "%s = %s;" % (
1133 Naming.retval_cname,
1134 err_val))
1136 if is_getbuffer_slot:
1137 self.getbuffer_error_cleanup(code)
1139 # If we are using the non-error cleanup section we should
1140 # jump past it if we have an error. The if-test below determine
1141 # whether this section is used.
1142 if buffers_present or is_getbuffer_slot:
1143 code.put_goto(code.return_from_error_cleanup_label)
1146 # ----- Non-error return cleanup
1147 # If you add anything here, remember to add a condition to the
1148 # if-test above in the error block (so that it can jump past this
1149 # block).
1150 code.put_label(code.return_label)
1151 for entry in lenv.buffer_entries:
1152 if entry.used:
1153 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1154 if is_getbuffer_slot:
1155 self.getbuffer_normal_cleanup(code)
1156 # ----- Return cleanup for both error and no-error return
1157 code.put_label(code.return_from_error_cleanup_label)
1158 if not Options.init_local_none:
1159 for entry in lenv.var_entries:
1160 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1161 entry.xdecref_cleanup = 1
1162 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1163 # Decref any increfed args
1164 for entry in lenv.arg_entries:
1165 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1166 code.put_var_decref(entry)
1168 # code.putln("/* TODO: decref scope object */")
1169 # ----- Return
1170 # This code is duplicated in ModuleNode.generate_module_init_func
1171 if not lenv.nogil:
1172 default_retval = self.return_type.default_value
1173 err_val = self.error_value()
1174 if err_val is None and default_retval:
1175 err_val = default_retval
1176 if self.return_type.is_pyobject:
1177 code.put_xgiveref(self.return_type.as_pyobject(Naming.retval_cname))
1179 code.put_finish_refcount_context()
1181 if self.entry.is_special and self.entry.name == "__hash__":
1182 # Returning -1 for __hash__ is supposed to signal an error
1183 # We do as Python instances and coerce -1 into -2.
1184 code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (Naming.retval_cname, Naming.retval_cname))
1186 if acquire_gil:
1187 code.putln("PyGILState_Release(_save);")
1189 if not self.return_type.is_void:
1190 code.putln("return %s;" % Naming.retval_cname)
1192 code.putln("}")
1193 # ----- Go back and insert temp variable declarations
1194 tempvardecl_code.put_temp_declarations(code.funcstate)
1195 # ----- Python version
1196 code.exit_cfunc_scope()
1197 if self.py_func:
1198 self.py_func.generate_function_definitions(env, code)
1199 self.generate_wrapper_functions(code)
1201 def declare_argument(self, env, arg):
1202 if arg.type.is_void:
1203 error(arg.pos, "Invalid use of 'void'")
1204 elif not arg.type.is_complete() and not arg.type.is_array:
1205 error(arg.pos,
1206 "Argument type '%s' is incomplete" % arg.type)
1207 return env.declare_arg(arg.name, arg.type, arg.pos)
1209 def generate_wrapper_functions(self, code):
1210 pass
1212 def generate_execution_code(self, code):
1213 # Evaluate and store argument default values
1214 for arg in self.args:
1215 default = arg.default
1216 if default:
1217 if not default.is_literal:
1218 default.generate_evaluation_code(code)
1219 default.make_owned_reference(code)
1220 result = default.result_as(arg.type)
1221 code.putln(
1222 "%s = %s;" % (
1223 arg.calculate_default_value_code(code),
1224 result))
1225 if arg.type.is_pyobject:
1226 code.put_giveref(default.result())
1227 default.generate_post_assignment_code(code)
1228 default.free_temps(code)
1229 # For Python class methods, create and store function object
1230 if self.assmt:
1231 self.assmt.generate_execution_code(code)
1233 #
1234 # Special code for the __getbuffer__ function
1235 #
1236 def getbuffer_init(self, code):
1237 info = self.local_scope.arg_entries[1].cname
1238 # Python 3.0 betas have a bug in memoryview which makes it call
1239 # getbuffer with a NULL parameter. For now we work around this;
1240 # the following line should be removed when this bug is fixed.
1241 code.putln("if (%s == NULL) return 0;" % info)
1242 code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
1243 code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
1245 def getbuffer_error_cleanup(self, code):
1246 info = self.local_scope.arg_entries[1].cname
1247 code.put_gotref("%s->obj" % info)
1248 code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
1249 (info, info))
1251 def getbuffer_normal_cleanup(self, code):
1252 info = self.local_scope.arg_entries[1].cname
1253 code.putln("if (%s->obj == Py_None) {" % info)
1254 code.put_gotref("Py_None")
1255 code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
1256 code.putln("}")
1258 class CFuncDefNode(FuncDefNode):
1259 # C function definition.
1260 #
1261 # modifiers ['inline']
1262 # visibility 'private' or 'public' or 'extern'
1263 # base_type CBaseTypeNode
1264 # declarator CDeclaratorNode
1265 # body StatListNode
1266 # api boolean
1267 # decorators [DecoratorNode] list of decorators
1268 #
1269 # with_gil boolean Acquire GIL around body
1270 # type CFuncType
1271 # py_func wrapper for calling from Python
1272 # overridable whether or not this is a cpdef function
1273 # inline_in_pxd whether this is an inline function in a pxd file
1275 child_attrs = ["base_type", "declarator", "body", "py_func"]
1277 inline_in_pxd = False
1278 decorators = None
1279 directive_locals = {}
1281 def unqualified_name(self):
1282 return self.entry.name
1284 def analyse_declarations(self, env):
1285 directive_locals = self.directive_locals = env.directives['locals']
1286 base_type = self.base_type.analyse(env)
1287 # The 2 here is because we need both function and argument names.
1288 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1289 if not type.is_cfunction:
1290 error(self.pos,
1291 "Suite attached to non-function declaration")
1292 # Remember the actual type according to the function header
1293 # written here, because the type in the symbol table entry
1294 # may be different if we're overriding a C method inherited
1295 # from the base type of an extension type.
1296 self.type = type
1297 type.is_overridable = self.overridable
1298 declarator = self.declarator
1299 while not hasattr(declarator, 'args'):
1300 declarator = declarator.base
1301 self.args = declarator.args
1302 for formal_arg, type_arg in zip(self.args, type.args):
1303 formal_arg.type = type_arg.type
1304 formal_arg.name = type_arg.name
1305 formal_arg.cname = type_arg.cname
1306 name = name_declarator.name
1307 cname = name_declarator.cname
1308 self.entry = env.declare_cfunction(
1309 name, type, self.pos,
1310 cname = cname, visibility = self.visibility,
1311 defining = self.body is not None,
1312 api = self.api, modifiers = self.modifiers)
1313 self.entry.inline_func_in_pxd = self.inline_in_pxd
1314 self.return_type = type.return_type
1316 if self.overridable and not env.is_module_scope:
1317 if len(self.args) < 1 or not self.args[0].type.is_pyobject:
1318 # An error will be produced in the cdef function
1319 self.overridable = False
1321 if self.overridable:
1322 import ExprNodes
1323 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1324 self.py_func = DefNode(pos = self.pos,
1325 name = self.entry.name,
1326 args = self.args,
1327 star_arg = None,
1328 starstar_arg = None,
1329 doc = self.doc,
1330 body = py_func_body,
1331 is_wrapper = 1)
1332 self.py_func.is_module_scope = env.is_module_scope
1333 self.py_func.analyse_declarations(env)
1334 self.entry.as_variable = self.py_func.entry
1335 # Reset scope entry the above cfunction
1336 env.entries[name] = self.entry
1337 if not env.is_module_scope or Options.lookup_module_cpdef:
1338 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1339 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1341 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1342 import ExprNodes
1343 args = self.type.args
1344 if omit_optional_args:
1345 args = args[:len(args) - self.type.optional_arg_count]
1346 arg_names = [arg.name for arg in args]
1347 if is_module_scope:
1348 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1349 else:
1350 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1351 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1352 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1353 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)
1354 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1356 def declare_arguments(self, env):
1357 for arg in self.type.args:
1358 if not arg.name:
1359 error(arg.pos, "Missing argument name")
1360 self.declare_argument(env, arg)
1362 def need_gil_acquisition(self, lenv):
1363 return self.type.with_gil
1365 def nogil_check(self, env):
1366 type = self.type
1367 with_gil = type.with_gil
1368 if type.nogil and not with_gil:
1369 if type.return_type.is_pyobject:
1370 error(self.pos,
1371 "Function with Python return type cannot be declared nogil")
1372 for entry in self.local_scope.var_entries:
1373 if entry.type.is_pyobject:
1374 error(self.pos, "Function declared nogil has Python locals or temporaries")
1376 def analyse_expressions(self, env):
1377 self.local_scope.directives = env.directives
1378 if self.py_func is not None:
1379 # this will also analyse the default values
1380 self.py_func.analyse_expressions(env)
1381 else:
1382 self.analyse_default_values(env)
1384 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1385 arg_decls = []
1386 type = self.type
1387 visibility = self.entry.visibility
1388 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1389 arg_decls.append(arg.declaration_code())
1390 if with_dispatch and self.overridable:
1391 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1392 if type.optional_arg_count and with_opt_args:
1393 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1394 if type.has_varargs:
1395 arg_decls.append("...")
1396 if not arg_decls:
1397 arg_decls = ["void"]
1398 if cname is None:
1399 cname = self.entry.func_cname
1400 entity = type.function_header_code(cname, ', '.join(arg_decls))
1401 if visibility == 'public':
1402 dll_linkage = "DL_EXPORT"
1403 else:
1404 dll_linkage = None
1405 header = self.return_type.declaration_code(entity,
1406 dll_linkage = dll_linkage)
1407 if visibility == 'extern':
1408 storage_class = "%s " % Naming.extern_c_macro
1409 elif visibility == 'public':
1410 storage_class = ""
1411 else:
1412 storage_class = "static "
1413 code.putln("%s%s %s {" % (
1414 storage_class,
1415 ' '.join(self.modifiers).upper(), # macro forms
1416 header))
1418 def generate_argument_declarations(self, env, code):
1419 for arg in self.args:
1420 if arg.default:
1421 result = arg.calculate_default_value_code(code)
1422 code.putln('%s = %s;' % (
1423 arg.type.declaration_code(arg.cname), result))
1425 def generate_keyword_list(self, code):
1426 pass
1428 def generate_argument_parsing_code(self, env, code):
1429 i = 0
1430 if self.type.optional_arg_count:
1431 code.putln('if (%s) {' % Naming.optional_args_cname)
1432 for arg in self.args:
1433 if arg.default:
1434 # FIXME: simple name prefixing doesn't work when
1435 # argument name mangling is in place
1436 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1437 declarator = arg.declarator
1438 while not hasattr(declarator, 'name'):
1439 declarator = declarator.base
1440 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1441 i += 1
1442 for _ in range(self.type.optional_arg_count):
1443 code.putln('}')
1444 code.putln('}')
1446 def generate_argument_conversion_code(self, code):
1447 pass
1449 def generate_argument_type_tests(self, code):
1450 # Generate type tests for args whose type in a parent
1451 # class is a supertype of the declared type.
1452 for arg in self.type.args:
1453 if arg.needs_type_test:
1454 self.generate_arg_type_test(arg, code)
1456 def generate_arg_type_test(self, arg, code):
1457 # Generate type test for one argument.
1458 if arg.type.typeobj_is_available():
1459 typeptr_cname = arg.type.typeptr_cname
1460 arg_code = "((PyObject *)%s)" % arg.cname
1461 code.putln(
1462 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1463 arg_code,
1464 typeptr_cname,
1465 not arg.not_none,
1466 arg.name,
1467 type.is_builtin_type,
1468 code.error_goto(arg.pos)))
1469 else:
1470 error(arg.pos, "Cannot test type of extern C class "
1471 "without type object name specification")
1473 def error_value(self):
1474 if self.return_type.is_pyobject:
1475 return "0"
1476 else:
1477 #return None
1478 return self.entry.type.exception_value
1480 def caller_will_check_exceptions(self):
1481 return self.entry.type.exception_check
1483 def generate_wrapper_functions(self, code):
1484 # If the C signature of a function has changed, we need to generate
1485 # wrappers to put in the slots here.
1486 k = 0
1487 entry = self.entry
1488 func_type = entry.type
1489 while entry.prev_entry is not None:
1490 k += 1
1491 entry = entry.prev_entry
1492 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1493 code.putln()
1494 self.generate_function_header(code,
1495 0,
1496 with_dispatch = entry.type.is_overridable,
1497 with_opt_args = entry.type.optional_arg_count,
1498 cname = entry.func_cname)
1499 if not self.return_type.is_void:
1500 code.put('return ')
1501 args = self.type.args
1502 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1503 if entry.type.is_overridable:
1504 arglist.append(Naming.skip_dispatch_cname)
1505 elif func_type.is_overridable:
1506 arglist.append('0')
1507 if entry.type.optional_arg_count:
1508 arglist.append(Naming.optional_args_cname)
1509 elif func_type.optional_arg_count:
1510 arglist.append('NULL')
1511 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1512 code.putln('}')
1515 class PyArgDeclNode(Node):
1516 # Argument which must be a Python object (used
1517 # for * and ** arguments).
1518 #
1519 # name string
1520 # entry Symtab.Entry
1521 child_attrs = []
1524 class DecoratorNode(Node):
1525 # A decorator
1526 #
1527 # decorator NameNode or CallNode
1528 child_attrs = ['decorator']
1531 class DefNode(FuncDefNode):
1532 # A Python function definition.
1533 #
1534 # name string the Python name of the function
1535 # decorators [DecoratorNode] list of decorators
1536 # args [CArgDeclNode] formal arguments
1537 # star_arg PyArgDeclNode or None * argument
1538 # starstar_arg PyArgDeclNode or None ** argument
1539 # doc EncodedString or None
1540 # body StatListNode
1541 #
1542 # The following subnode is constructed internally
1543 # when the def statement is inside a Python class definition.
1544 #
1545 # assmt AssignmentNode Function construction/assignment
1547 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1549 assmt = None
1550 num_kwonly_args = 0
1551 num_required_kw_args = 0
1552 reqd_kw_flags_cname = "0"
1553 is_wrapper = 0
1554 decorators = None
1555 entry = None
1558 def __init__(self, pos, **kwds):
1559 FuncDefNode.__init__(self, pos, **kwds)
1560 k = rk = r = 0
1561 for arg in self.args:
1562 if arg.kw_only:
1563 k += 1
1564 if not arg.default:
1565 rk += 1
1566 if not arg.default:
1567 r += 1
1568 self.num_kwonly_args = k
1569 self.num_required_kw_args = rk
1570 self.num_required_args = r
1572 def as_cfunction(self, cfunc=None, scope=None):
1573 if self.star_arg:
1574 error(self.star_arg.pos, "cdef function cannot have star argument")
1575 if self.starstar_arg:
1576 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1577 if cfunc is None:
1578 cfunc_args = []
1579 for formal_arg in self.args:
1580 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1581 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1582 cname = None,
1583 type = py_object_type,
1584 pos = formal_arg.pos))
1585 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1586 args = cfunc_args,
1587 has_varargs = False,
1588 exception_value = None,
1589 exception_check = False,
1590 nogil = False,
1591 with_gil = False,
1592 is_overridable = True)
1593 cfunc = CVarDefNode(self.pos, type=cfunc_type)
1594 else:
1595 cfunc_type = cfunc.type
1596 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1597 error(self.pos, "wrong number of arguments")
1598 error(declarator.pos, "previous declaration here")
1599 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1600 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1601 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1602 formal_arg.type = type_arg.type
1603 formal_arg.name_declarator = name_declarator
1604 import ExprNodes
1605 if cfunc_type.exception_value is None:
1606 exception_value = None
1607 else:
1608 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1609 declarator = CFuncDeclaratorNode(self.pos,
1610 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1611 args = self.args,
1612 has_varargs = False,
1613 exception_check = cfunc_type.exception_check,
1614 exception_value = exception_value,
1615 with_gil = cfunc_type.with_gil,
1616 nogil = cfunc_type.nogil)
1617 return CFuncDefNode(self.pos,
1618 modifiers = [],
1619 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1620 declarator = declarator,
1621 body = self.body,
1622 doc = self.doc,
1623 overridable = cfunc_type.is_overridable,
1624 type = cfunc_type,
1625 with_gil = cfunc_type.with_gil,
1626 nogil = cfunc_type.nogil,
1627 visibility = 'private',
1628 api = False,
1629 directive_locals = getattr(cfunc, 'directive_locals', {}))
1631 def analyse_declarations(self, env):
1632 directive_locals = self.directive_locals = env.directives['locals']
1633 for arg in self.args:
1634 if hasattr(arg, 'name'):
1635 type = arg.type
1636 name_declarator = None
1637 else:
1638 base_type = arg.base_type.analyse(env)
1639 name_declarator, type = \
1640 arg.declarator.analyse(base_type, env)
1641 arg.name = name_declarator.name
1642 if arg.name in directive_locals:
1643 type_node = directive_locals[arg.name]
1644 other_type = type_node.analyse_as_type(env)
1645 if other_type is None:
1646 error(type_node.pos, "Not a type")
1647 elif (type is not PyrexTypes.py_object_type
1648 and not type.same_as(other_type)):
1649 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1650 error(type_node.pos, "Previous declaration here")
1651 else:
1652 type = other_type
1653 if name_declarator and name_declarator.cname:
1654 error(self.pos,
1655 "Python function argument cannot have C name specification")
1656 arg.type = type.as_argument_type()
1657 arg.hdr_type = None
1658 arg.needs_conversion = 0
1659 arg.needs_type_test = 0
1660 arg.is_generic = 1
1661 if arg.not_none and not arg.type.is_extension_type:
1662 error(self.pos,
1663 "Only extension type arguments can have 'not None'")
1664 self.declare_pyfunction(env)
1665 self.analyse_signature(env)
1666 self.return_type = self.entry.signature.return_type()
1668 def analyse_signature(self, env):
1669 any_type_tests_needed = 0
1670 if self.entry.is_special:
1671 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1672 elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
1673 # Use the simpler calling signature for zero- and one-argument functions.
1674 if self.entry.signature is TypeSlots.pyfunction_signature:
1675 if len(self.args) == 0:
1676 self.entry.signature = TypeSlots.pyfunction_noargs
1677 elif len(self.args) == 1:
1678 if self.args[0].default is None and not self.args[0].kw_only:
1679 self.entry.signature = TypeSlots.pyfunction_onearg
1680 elif self.entry.signature is TypeSlots.pymethod_signature:
1681 if len(self.args) == 1:
1682 self.entry.signature = TypeSlots.unaryfunc
1683 elif len(self.args) == 2:
1684 if self.args[1].default is None and not self.args[1].kw_only:
1685 self.entry.signature = TypeSlots.ibinaryfunc
1686 sig = self.entry.signature
1687 nfixed = sig.num_fixed_args()
1688 for i in range(nfixed):
1689 if i < len(self.args):
1690 arg = self.args[i]
1691 arg.is_generic = 0
1692 if sig.is_self_arg(i):
1693 arg.is_self_arg = 1
1694 arg.hdr_type = arg.type = env.parent_type
1695 arg.needs_conversion = 0
1696 else:
1697 arg.hdr_type = sig.fixed_arg_type(i)
1698 if not arg.type.same_as(arg.hdr_type):
1699 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1700 arg.needs_type_test = 1
1701 any_type_tests_needed = 1
1702 else:
1703 arg.needs_conversion = 1
1704 if arg.needs_conversion:
1705 arg.hdr_cname = Naming.arg_prefix + arg.name
1706 else:
1707 arg.hdr_cname = Naming.var_prefix + arg.name
1708 else:
1709 self.bad_signature()
1710 return
1711 if nfixed < len(self.args):
1712 if not sig.has_generic_args:
1713 self.bad_signature()
1714 for arg in self.args:
1715 if arg.is_generic and \
1716 (arg.type.is_extension_type or arg.type.is_builtin_type):
1717 arg.needs_type_test = 1
1718 any_type_tests_needed = 1
1719 if any_type_tests_needed:
1720 env.use_utility_code(arg_type_test_utility_code)
1722 def bad_signature(self):
1723 sig = self.entry.signature
1724 expected_str = "%d" % sig.num_fixed_args()
1725 if sig.has_generic_args:
1726 expected_str = expected_str + " or more"
1727 name = self.name
1728 if name.startswith("__") and name.endswith("__"):
1729 desc = "Special method"
1730 else:
1731 desc = "Method"
1732 error(self.pos,
1733 "%s %s has wrong number of arguments "
1734 "(%d declared, %s expected)" % (
1735 desc, self.name, len(self.args), expected_str))
1737 def signature_has_nongeneric_args(self):
1738 argcount = len(self.args)
1739 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1740 return 0
1741 return 1
1743 def signature_has_generic_args(self):
1744 return self.entry.signature.has_generic_args
1746 def declare_pyfunction(self, env):
1747 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1748 name = self.name
1749 entry = env.lookup_here(self.name)
1750 if entry and entry.type.is_cfunction and not self.is_wrapper:
1751 warning(self.pos, "Overriding cdef method with def method.", 5)
1752 entry = env.declare_pyfunction(self.name, self.pos)
1753 self.entry = entry
1754 prefix = env.scope_prefix
1755 entry.func_cname = \
1756 Naming.pyfunc_prefix + prefix + name
1757 entry.pymethdef_cname = \
1758 Naming.pymethdef_prefix + prefix + name
1759 if Options.docstrings:
1760 entry.doc = embed_position(self.pos, self.doc)
1761 entry.doc_cname = \
1762 Naming.funcdoc_prefix + prefix + name
1763 else:
1764 entry.doc = None
1766 def declare_arguments(self, env):
1767 for arg in self.args:
1768 if not arg.name:
1769 error(arg.pos, "Missing argument name")
1770 if arg.needs_conversion:
1771 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1772 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1773 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1774 if arg.type.is_pyobject:
1775 arg.entry.init = "0"
1776 arg.entry.init_to_none = 0
1777 else:
1778 arg.entry = self.declare_argument(env, arg)
1779 arg.entry.used = 1
1780 arg.entry.is_self_arg = arg.is_self_arg
1781 if arg.hdr_type:
1782 if arg.is_self_arg or \
1783 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1784 arg.entry.is_declared_generic = 1
1785 self.declare_python_arg(env, self.star_arg)
1786 self.declare_python_arg(env, self.starstar_arg)
1788 def declare_python_arg(self, env, arg):
1789 if arg:
1790 entry = env.declare_var(arg.name,
1791 PyrexTypes.py_object_type, arg.pos)
1792 entry.used = 1
1793 entry.init = "0"
1794 entry.init_to_none = 0
1795 entry.xdecref_cleanup = 1
1796 arg.entry = entry
1797 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1799 def analyse_expressions(self, env):
1800 self.local_scope.directives = env.directives
1801 self.analyse_default_values(env)
1802 if env.is_py_class_scope:
1803 self.synthesize_assignment_node(env)
1805 def synthesize_assignment_node(self, env):
1806 import ExprNodes
1807 self.assmt = SingleAssignmentNode(self.pos,
1808 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1809 rhs = ExprNodes.UnboundMethodNode(self.pos,
1810 function = ExprNodes.PyCFunctionNode(self.pos,
1811 pymethdef_cname = self.entry.pymethdef_cname)))
1812 self.assmt.analyse_declarations(env)
1813 self.assmt.analyse_expressions(env)
1815 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1816 arg_code_list = []
1817 sig = self.entry.signature
1818 if sig.has_dummy_arg:
1819 arg_code_list.append(
1820 "PyObject *%s" % Naming.self_cname)
1821 for arg in self.args:
1822 if not arg.is_generic:
1823 if arg.is_self_arg:
1824 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1825 else:
1826 arg_code_list.append(
1827 arg.hdr_type.declaration_code(arg.hdr_cname))
1828 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1829 arg_code_list.append("PyObject *unused")
1830 if sig.has_generic_args:
1831 arg_code_list.append(
1832 "PyObject *%s, PyObject *%s"
1833 % (Naming.args_cname, Naming.kwds_cname))
1834 arg_code = ", ".join(arg_code_list)
1835 dc = self.return_type.declaration_code(self.entry.func_cname)
1836 header = "static %s(%s)" % (dc, arg_code)
1837 code.putln("%s; /*proto*/" % header)
1838 if proto_only:
1839 return
1840 if self.entry.doc and Options.docstrings:
1841 docstr = self.entry.doc
1842 if not isinstance(docstr, str):
1843 docstr = docstr.utf8encode()
1844 code.putln(
1845 'static char %s[] = "%s";' % (
1846 self.entry.doc_cname,
1847 split_docstring(escape_byte_string(docstr))))
1848 if with_pymethdef:
1849 code.put(
1850 "static PyMethodDef %s = " %
1851 self.entry.pymethdef_cname)
1852 code.put_pymethoddef(self.entry, ";")
1853 code.putln("%s {" % header)
1855 def generate_argument_declarations(self, env, code):
1856 for arg in self.args:
1857 if arg.is_generic: # or arg.needs_conversion:
1858 if arg.needs_conversion:
1859 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1860 else:
1861 code.put_var_declaration(arg.entry)
1863 def generate_keyword_list(self, code):
1864 if self.signature_has_generic_args() and \
1865 self.signature_has_nongeneric_args():
1866 code.put(
1867 "static PyObject **%s[] = {" %
1868 Naming.pykwdlist_cname)
1869 for arg in self.args:
1870 if arg.is_generic:
1871 pystring_cname = code.intern_identifier(arg.name)
1872 code.put('&%s,' % pystring_cname)
1873 code.putln("0};")
1875 def generate_argument_parsing_code(self, env, code):
1876 # Generate PyArg_ParseTuple call for generic
1877 # arguments, if any.
1878 if self.entry.signature.has_dummy_arg:
1879 # get rid of unused argument warning
1880 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1882 old_error_label = code.new_error_label()
1883 our_error_label = code.error_label
1884 end_label = code.new_label("argument_unpacking_done")
1886 has_kwonly_args = self.num_kwonly_args > 0
1887 has_star_or_kw_args = self.star_arg is not None \
1888 or self.starstar_arg is not None or has_kwonly_args
1890 for arg in self.args:
1891 if not arg.type.is_pyobject and arg.type.from_py_function is None:
1892 arg.type.create_from_py_utility_code(env)
1894 if not self.signature_has_generic_args():
1895 if has_star_or_kw_args:
1896 error(self.pos, "This method cannot have * or keyword arguments")
1897 self.generate_argument_conversion_code(code)
1899 elif not self.signature_has_nongeneric_args():
1900 # func(*args) or func(**kw) or func(*args, **kw)
1901 self.generate_stararg_copy_code(code)
1903 else:
1904 positional_args = []
1905 kw_only_args = []
1906 default_seen = 0
1907 for arg in self.args:
1908 arg_entry = arg.entry
1909 if arg.is_generic:
1910 if arg.default:
1911 default_seen = 1
1912 if not arg.is_self_arg:
1913 if arg.kw_only:
1914 kw_only_args.append(arg)
1915 else:
1916 positional_args.append(arg)
1917 elif arg.kw_only:
1918 kw_only_args.append(arg)
1919 default_seen = 1
1920 elif default_seen:
1921 error(arg.pos, "Non-default argument following default argument")
1922 elif not arg.is_self_arg:
1923 positional_args.append(arg)
1925 self.generate_tuple_and_keyword_parsing_code(
1926 positional_args, kw_only_args, end_label, code)
1928 code.error_label = old_error_label
1929 if code.label_used(our_error_label):
1930 if not code.label_used(end_label):
1931 code.put_goto(end_label)
1932 code.put_label(our_error_label)
1933 if has_star_or_kw_args:
1934 self.generate_arg_decref(self.star_arg, code)
1935 if self.starstar_arg:
1936 if self.starstar_arg.entry.xdecref_cleanup:
1937 code.put_var_xdecref(self.starstar_arg.entry)
1938 else:
1939 code.put_var_decref(self.starstar_arg.entry)
1940 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1941 code.putln("return %s;" % self.error_value())
1942 if code.label_used(end_label):
1943 code.put_label(end_label)
1945 def generate_arg_assignment(self, arg, item, code):
1946 if arg.type.is_pyobject:
1947 if arg.is_generic:
1948 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1949 code.putln("%s = %s;" % (arg.entry.cname, item))
1950 else:
1951 func = arg.type.from_py_function
1952 if func:
1953 code.putln("%s = %s(%s); %s" % (
1954 arg.entry.cname,
1955 func,
1956 item,
1957 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1958 else:
1959 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1961 def generate_arg_xdecref(self, arg, code):
1962 if arg:
1963 code.put_var_xdecref(arg.entry)
1965 def generate_arg_decref(self, arg, code):
1966 if arg:
1967 code.put_var_decref(arg.entry)
1969 def generate_stararg_copy_code(self, code):
1970 if not self.star_arg:
1971 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1972 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1973 Naming.args_cname)
1974 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1975 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1976 code.putln("}")
1978 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1980 if self.starstar_arg:
1981 if self.star_arg:
1982 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1983 else:
1984 kwarg_check = "%s" % Naming.kwds_cname
1985 else:
1986 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1987 Naming.kwds_cname, Naming.kwds_cname)
1988 code.putln(
1989 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1990 kwarg_check, Naming.kwds_cname, self.name,
1991 bool(self.starstar_arg), self.error_value()))
1993 if self.starstar_arg:
1994 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1995 self.starstar_arg.entry.cname,
1996 Naming.kwds_cname,
1997 Naming.kwds_cname))
1998 code.putln("if (unlikely(!%s)) return %s;" % (
1999 self.starstar_arg.entry.cname, self.error_value()))
2000 self.starstar_arg.entry.xdecref_cleanup = 0
2001 code.put_gotref(self.starstar_arg.entry.cname)
2004 if self.star_arg:
2005 code.put_incref(Naming.args_cname, py_object_type)
2006 code.putln("%s = %s;" % (
2007 self.star_arg.entry.cname,
2008 Naming.args_cname))
2009 self.star_arg.entry.xdecref_cleanup = 0
2011 def generate_tuple_and_keyword_parsing_code(self, positional_args,
2012 kw_only_args, success_label, code):
2013 argtuple_error_label = code.new_label("argtuple_error")
2015 min_positional_args = self.num_required_args - self.num_required_kw_args
2016 if len(self.args) > 0 and self.args[0].is_self_arg:
2017 min_positional_args -= 1
2018 max_positional_args = len(positional_args)
2019 has_fixed_positional_count = not self.star_arg and \
2020 min_positional_args == max_positional_args
2022 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
2023 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
2024 if self.num_required_kw_args:
2025 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
2027 if self.starstar_arg or self.star_arg:
2028 self.generate_stararg_init_code(max_positional_args, code)
2030 # --- optimised code when we receive keyword arguments
2031 if self.num_required_kw_args:
2032 likely_hint = "likely"
2033 else:
2034 likely_hint = "unlikely"
2035 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
2036 self.generate_keyword_unpacking_code(
2037 min_positional_args, max_positional_args,
2038 has_fixed_positional_count,
2039 positional_args, kw_only_args, argtuple_error_label, code)
2041 # --- optimised code when we do not receive any keyword arguments
2042 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
2043 # Python raises arg tuple related errors first, so we must
2044 # check the length here
2045 if min_positional_args == max_positional_args and not self.star_arg:
2046 compare = '!='
2047 else:
2048 compare = '<'
2049 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2050 Naming.args_cname, compare, min_positional_args))
2051 code.put_goto(argtuple_error_label)
2053 if self.num_required_kw_args:
2054 # pure error case: keywords required but not passed
2055 if max_positional_args > min_positional_args and not self.star_arg:
2056 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2057 Naming.args_cname, max_positional_args))
2058 code.put_goto(argtuple_error_label)
2059 code.putln('} else {')
2060 for i, arg in enumerate(kw_only_args):
2061 if not arg.default:
2062 pystring_cname = code.intern_identifier(arg.name)
2063 # required keyword-only argument missing
2064 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2065 self.name.utf8encode(),
2066 pystring_cname))
2067 code.putln(code.error_goto(self.pos))
2068 break
2070 elif min_positional_args == max_positional_args:
2071 # parse the exact number of positional arguments from the
2072 # args tuple
2073 code.putln('} else {')
2074 for i, arg in enumerate(positional_args):
2075 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2076 self.generate_arg_assignment(arg, item, code)
2077 self.generate_arg_default_assignments(code)
2079 else:
2080 # parse the positional arguments from the variable length
2081 # args tuple
2082 code.putln('} else {')
2083 self.generate_arg_default_assignments(code)
2084 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2085 if self.star_arg:
2086 code.putln('default:')
2087 reversed_args = list(enumerate(positional_args))[::-1]
2088 for i, arg in reversed_args:
2089 if i >= min_positional_args-1:
2090 if min_positional_args > 1:
2091 code.putln('case %2d:' % (i+1)) # pure code beautification
2092 else:
2093 code.put('case %2d: ' % (i+1))
2094 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2095 self.generate_arg_assignment(arg, item, code)
2096 if min_positional_args == 0:
2097 code.put('case 0: ')
2098 code.putln('break;')
2099 if self.star_arg:
2100 if min_positional_args:
2101 for i in range(min_positional_args-1, -1, -1):
2102 code.putln('case %2d:' % i)
2103 code.put_goto(argtuple_error_label)
2104 else:
2105 code.put('default: ')
2106 code.put_goto(argtuple_error_label)
2107 code.putln('}')
2109 code.putln('}')
2111 if code.label_used(argtuple_error_label):
2112 code.put_goto(success_label)
2113 code.put_label(argtuple_error_label)
2114 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2115 self.name.utf8encode(), has_fixed_positional_count,
2116 min_positional_args, max_positional_args,
2117 Naming.args_cname))
2118 code.putln(code.error_goto(self.pos))
2120 def generate_arg_default_assignments(self, code):
2121 for arg in self.args:
2122 if arg.is_generic and arg.default:
2123 code.putln(
2124 "%s = %s;" % (
2125 arg.entry.cname,
2126 arg.calculate_default_value_code(code)))
2128 def generate_stararg_init_code(self, max_positional_args, code):
2129 if self.starstar_arg:
2130 self.starstar_arg.entry.xdecref_cleanup = 0
2131 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2132 self.starstar_arg.entry.cname,
2133 self.starstar_arg.entry.cname,
2134 self.error_value()))
2135 code.put_gotref(self.starstar_arg.entry.cname)
2136 if self.star_arg:
2137 self.star_arg.entry.xdecref_cleanup = 0
2138 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2139 Naming.args_cname,
2140 max_positional_args))
2141 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2142 self.star_arg.entry.cname, Naming.args_cname,
2143 max_positional_args, Naming.args_cname))
2144 code.put_gotref(self.star_arg.entry.cname)
2145 if self.starstar_arg:
2146 code.putln("")
2147 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2148 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2149 code.putln('return %s;' % self.error_value())
2150 code.putln('}')
2151 else:
2152 code.putln("if (unlikely(!%s)) return %s;" % (
2153 self.star_arg.entry.cname, self.error_value()))
2154 code.putln('} else {')
2155 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2156 code.put_incref(Naming.empty_tuple, py_object_type)
2157 code.putln('}')
2159 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2160 has_fixed_positional_count, positional_args,
2161 kw_only_args, argtuple_error_label, code):
2162 all_args = tuple(positional_args) + tuple(kw_only_args)
2163 max_args = len(all_args)
2165 default_args = []
2166 for i, arg in enumerate(all_args):
2167 if arg.default and arg.type.is_pyobject:
2168 default_value = arg.calculate_default_value_code(code)
2169 if arg.type is not PyrexTypes.py_object_type:
2170 default_value = "(PyObject*)"+default_value
2171 default_args.append((i, default_value))
2173 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2174 Naming.kwds_cname)
2175 # it looks funny to separate the init-to-0 from setting the
2176 # default value, but C89 needs this
2177 code.putln("PyObject* values[%d] = {%s};" % (
2178 max_args, ','.join(['0']*max_args)))
2179 for i, default_value in default_args:
2180 code.putln('values[%d] = %s;' % (i, default_value))
2182 # parse the tuple and check that it's not too long
2183 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2184 if self.star_arg:
2185 code.putln('default:')
2186 for i in range(max_positional_args-1, -1, -1):
2187 code.put('case %2d: ' % (i+1))
2188 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2189 i, Naming.args_cname, i))
2190 code.putln('case 0: break;')
2191 if not self.star_arg:
2192 code.put('default: ') # more arguments than allowed
2193 code.put_goto(argtuple_error_label)
2194 code.putln('}')
2196 # now fill up the positional/required arguments with values
2197 # from the kw dict
2198 if self.num_required_args or max_positional_args > 0:
2199 last_required_arg = -1
2200 for i, arg in enumerate(all_args):
2201 if not arg.default:
2202 last_required_arg = i
2203 if last_required_arg < max_positional_args:
2204 last_required_arg = max_positional_args-1
2205 num_required_args = self.num_required_args
2206 if max_positional_args > 0:
2207 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2208 for i, arg in enumerate(all_args[:last_required_arg+1]):
2209 if max_positional_args > 0 and i <= max_positional_args:
2210 if self.star_arg and i == max_positional_args:
2211 code.putln('default:')
2212 else:
2213 code.putln('case %2d:' % i)
2214 pystring_cname = code.intern_identifier(arg.name)
2215 if arg.default:
2216 if arg.kw_only:
2217 # handled separately below
2218 continue
2219 code.putln('if (kw_args > %d) {' % num_required_args)
2220 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
2221 Naming.kwds_cname, pystring_cname))
2222 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
2223 code.putln('}')
2224 else:
2225 num_required_args -= 1
2226 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2227 i, Naming.kwds_cname, pystring_cname))
2228 code.putln('if (likely(values[%d])) kw_args--;' % i);
2229 if i < min_positional_args:
2230 if i == 0:
2231 # special case: we know arg 0 is missing
2232 code.put('else ')
2233 code.put_goto(argtuple_error_label)
2234 else:
2235 # print the correct number of values (args or
2236 # kwargs) that were passed into positional
2237 # arguments up to this point
2238 code.putln('else {')
2239 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2240 self.name.utf8encode(), has_fixed_positional_count,
2241 min_positional_args, max_positional_args, i))
2242 code.putln(code.error_goto(self.pos))
2243 code.putln('}')
2244 elif arg.kw_only:
2245 code.putln('else {')
2246 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2247 self.name.utf8encode(), pystring_cname))
2248 code.putln(code.error_goto(self.pos))
2249 code.putln('}')
2250 if max_positional_args > 0:
2251 code.putln('}')
2253 if kw_only_args and not self.starstar_arg:
2254 # unpack optional keyword-only arguments
2255 # checking for interned strings in a dict is faster than iterating
2256 # but it's too likely that we must iterate if we expect **kwargs
2257 optional_args = []
2258 for i, arg in enumerate(all_args[max_positional_args:]):
2259 if not arg.kw_only or not arg.default:
2260 continue
2261 optional_args.append((i+max_positional_args, arg))
2262 if optional_args:
2263 # this mimics an unrolled loop so that we can "break" out of it
2264 code.putln('while (kw_args > 0) {')
2265 code.putln('PyObject* value;')
2266 for i, arg in optional_args:
2267 pystring_cname = code.intern_identifier(arg.name)
2268 code.putln(
2269 'value = PyDict_GetItem(%s, %s);' % (
2270 Naming.kwds_cname, pystring_cname))
2271 code.putln(
2272 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
2273 code.putln('break;')
2274 code.putln('}')
2276 code.putln('if (unlikely(kw_args > 0)) {')
2277 # non-positional/-required kw args left in dict: default args,
2278 # kw-only args, **kwargs or error
2279 #
2280 # This is sort of a catch-all: except for checking required
2281 # arguments, this will always do the right thing for unpacking
2282 # keyword arguments, so that we can concentrate on optimising
2283 # common cases above.
2284 if max_positional_args == 0:
2285 pos_arg_count = "0"
2286 elif self.star_arg:
2287 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2288 Naming.args_cname, max_positional_args,
2289 Naming.args_cname, max_positional_args))
2290 pos_arg_count = "used_pos_args"
2291 else:
2292 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2293 code.globalstate.use_utility_code(parse_keywords_utility_code)
2294 code.put(
2295 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2296 Naming.kwds_cname,
2297 Naming.pykwdlist_cname,
2298 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2299 pos_arg_count,
2300 self.name.utf8encode()))
2301 code.putln(code.error_goto(self.pos))
2302 code.putln('}')
2304 # convert arg values to their final type and assign them
2305 for i, arg in enumerate(all_args):
2306 if arg.default and not arg.type.is_pyobject:
2307 code.putln("if (values[%d]) {" % i)
2308 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2309 if arg.default and not arg.type.is_pyobject:
2310 code.putln('} else {')
2311 code.putln(
2312 "%s = %s;" % (
2313 arg.entry.cname,
2314 arg.calculate_default_value_code(code)))
2315 code.putln('}')
2317 def generate_argument_conversion_code(self, code):
2318 # Generate code to convert arguments from
2319 # signature type to declared type, if needed.
2320 for arg in self.args:
2321 if arg.needs_conversion:
2322 self.generate_arg_conversion(arg, code)
2324 def generate_arg_conversion(self, arg, code):
2325 # Generate conversion code for one argument.
2326 old_type = arg.hdr_type
2327 new_type = arg.type
2328 if old_type.is_pyobject:
2329 if arg.default:
2330 code.putln("if (%s) {" % arg.hdr_cname)
2331 else:
2332 code.putln("assert(%s); {" % arg.hdr_cname)
2333 self.generate_arg_conversion_from_pyobject(arg, code)
2334 code.putln("}")
2335 elif new_type.is_pyobject:
2336 self.generate_arg_conversion_to_pyobject(arg, code)
2337 else:
2338 if new_type.assignable_from(old_type):
2339 code.putln(
2340 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2341 else:
2342 error(arg.pos,
2343 "Cannot convert 1 argument from '%s' to '%s'" %
2344 (old_type, new_type))
2346 def generate_arg_conversion_from_pyobject(self, arg, code):
2347 new_type = arg.type
2348 func = new_type.from_py_function
2349 # copied from CoerceFromPyTypeNode
2350 if func:
2351 code.putln("%s = %s(%s); %s" % (
2352 arg.entry.cname,
2353 func,
2354 arg.hdr_cname,
2355 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2356 else:
2357 error(arg.pos,
2358 "Cannot convert Python object argument to type '%s'"
2359 % new_type)
2361 def generate_arg_conversion_to_pyobject(self, arg, code):
2362 old_type = arg.hdr_type
2363 func = old_type.to_py_function
2364 if func:
2365 code.putln("%s = %s(%s); %s" % (
2366 arg.entry.cname,
2367 func,
2368 arg.hdr_cname,
2369 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2370 code.put_var_gotref(arg.entry)
2371 else:
2372 error(arg.pos,
2373 "Cannot convert argument of type '%s' to Python object"
2374 % old_type)
2376 def generate_argument_type_tests(self, code):
2377 # Generate type tests for args whose signature
2378 # type is PyObject * and whose declared type is
2379 # a subtype thereof.
2380 for arg in self.args:
2381 if arg.needs_type_test:
2382 self.generate_arg_type_test(arg, code)
2384 def generate_arg_type_test(self, arg, code):
2385 # Generate type test for one argument.
2386 if arg.type.typeobj_is_available():
2387 typeptr_cname = arg.type.typeptr_cname
2388 arg_code = "((PyObject *)%s)" % arg.entry.cname
2389 code.putln(
2390 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2391 arg_code,
2392 typeptr_cname,
2393 not arg.not_none,
2394 arg.name,
2395 arg.type.is_builtin_type,
2396 code.error_goto(arg.pos)))
2397 else:
2398 error(arg.pos, "Cannot test type of extern C class "
2399 "without type object name specification")
2401 def error_value(self):
2402 return self.entry.signature.error_value
2404 def caller_will_check_exceptions(self):
2405 return 1
2407 class OverrideCheckNode(StatNode):
2408 # A Node for dispatching to the def method if it
2409 # is overriden.
2410 #
2411 # py_func
2412 #
2413 # args
2414 # func_temp
2415 # body
2417 child_attrs = ['body']
2419 body = None
2421 def analyse_expressions(self, env):
2422 self.args = env.arg_entries
2423 if self.py_func.is_module_scope:
2424 first_arg = 0
2425 else:
2426 first_arg = 1
2427 import ExprNodes
2428 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2429 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2430 call_node = ExprNodes.SimpleCallNode(self.pos,
2431 function=self.func_node,
2432 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2433 self.body = ReturnStatNode(self.pos, value=call_node)
2434 self.body.analyse_expressions(env)
2436 def generate_execution_code(self, code):
2437 interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
2438 # Check to see if we are an extension type
2439 if self.py_func.is_module_scope:
2440 self_arg = "((PyObject *)%s)" % Naming.module_cname
2441 else:
2442 self_arg = "((PyObject *)%s)" % self.args[0].cname
2443 code.putln("/* Check if called by wrapper */")
2444 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2445 code.putln("/* Check if overriden in Python */")
2446 if self.py_func.is_module_scope:
2447 code.putln("else {")
2448 else:
2449 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2450 self.func_node.allocate(code)
2451 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2452 # need to get attribute manually--scope would return cdef method
2453 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
2454 self.func_node.result(), self_arg, interned_attr_cname, err))
2455 code.put_gotref(self.func_node.py_result())
2456 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
2457 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (
2458 self.func_node.result(), self.py_func.entry.func_cname)
2459 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2460 self.body.generate_execution_code(code)
2461 code.putln('}')
2462 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2463 code.putln("}")
2464 self.func_node.release(code)
2466 class ClassDefNode(StatNode, BlockNode):
2467 pass
2469 class PyClassDefNode(ClassDefNode):
2470 # A Python class definition.
2471 #
2472 # name EncodedString Name of the class
2473 # doc string or None
2474 # body StatNode Attribute definition code
2475 # entry Symtab.Entry
2476 # scope PyClassScope
2477 # decorators [DecoratorNode] list of decorators or None
2478 #
2479 # The following subnodes are constructed internally:
2480 #
2481 # dict DictNode Class dictionary
2482 # classobj ClassNode Class object
2483 # target NameNode Variable to assign class object to
2485 child_attrs = ["body", "dict", "classobj", "target"]
2486 decorators = None
2488 def __init__(self, pos, name, bases, doc, body, decorators = None):
2489 StatNode.__init__(self, pos)
2490 self.name = name
2491 self.doc = doc
2492 self.body = body
2493 self.decorators = decorators
2494 import ExprNodes
2495 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2496 if self.doc and Options.docstrings:
2497 doc = embed_position(self.pos, self.doc)
2498 doc_node = ExprNodes.StringNode(pos, value = doc)
2499 else:
2500 doc_node = None
2501 self.classobj = ExprNodes.ClassNode(pos, name = name,
2502 bases = bases, dict = self.dict, doc = doc_node)
2503 self.target = ExprNodes.NameNode(pos, name = name)
2505 def as_cclass(self):
2506 """
2507 Return this node as if it were declared as an extension class
2508 """
2509 bases = self.classobj.bases.args
2510 if len(bases) == 0:
2511 base_class_name = None
2512 base_class_module = None
2513 elif len(bases) == 1:
2514 base = bases[0]
2515 path = []
2516 from ExprNodes import AttributeNode, NameNode
2517 while isinstance(base, AttributeNode):
2518 path.insert(0, base.attribute)
2519 base = base.obj
2520 if isinstance(base, NameNode):
2521 path.insert(0, base.name)
2522 base_class_name = path[-1]
2523 if len(path) > 1:
2524 base_class_module = u'.'.join(path[:-1])
2525 else:
2526 base_class_module = None
2527 else:
2528 error(self.classobj.bases.args.pos, "Invalid base class")
2529 else:
2530 error(self.classobj.bases.args.pos, "C class may only have one base class")
2531 return None
2533 return CClassDefNode(self.pos,
2534 visibility = 'private',
2535 module_name = None,
2536 class_name = self.name,
2537 base_class_module = base_class_module,
2538 base_class_name = base_class_name,
2539 decorators = self.decorators,
2540 body = self.body,
2541 in_pxd = False,
2542 doc = self.doc)
2544 def create_scope(self, env):
2545 genv = env
2546 while env.is_py_class_scope or env.is_c_class_scope:
2547 env = env.outer_scope
2548 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2549 return cenv
2551 def analyse_declarations(self, env):
2552 self.target.analyse_target_declaration(env)
2553 cenv = self.create_scope(env)
2554 cenv.directives = env.directives
2555 cenv.class_obj_cname = self.target.entry.cname
2556 self.body.analyse_declarations(cenv)
2558 def analyse_expressions(self, env):
2559 self.dict.analyse_expressions(env)
2560 self.classobj.analyse_expressions(env)
2561 genv = env.global_scope()
2562 cenv = self.scope
2563 self.body.analyse_expressions(cenv)
2564 self.target.analyse_target_expression(env, self.classobj)
2566 def generate_function_definitions(self, env, code):
2567 self.body.generate_function_definitions(self.scope, code)
2569 def generate_execution_code(self, code):
2570 code.pyclass_stack.append(self)
2571 cenv = self.scope
2572 self.dict.generate_evaluation_code(code)
2573 self.classobj.generate_evaluation_code(code)
2574 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2575 self.body.generate_execution_code(code)
2576 self.target.generate_assignment_code(self.classobj, code)
2577 self.dict.generate_disposal_code(code)
2578 self.dict.free_temps(code)
2579 code.pyclass_stack.pop()
2582 class CClassDefNode(ClassDefNode):
2583 # An extension type definition.
2584 #
2585 # visibility 'private' or 'public' or 'extern'
2586 # typedef_flag boolean
2587 # api boolean
2588 # module_name string or None For import of extern type objects
2589 # class_name string Unqualified name of class
2590 # as_name string or None Name to declare as in this scope
2591 # base_class_module string or None Module containing the base class
2592 # base_class_name string or None Name of the base class
2593 # objstruct_name string or None Specified C name of object struct
2594 # typeobj_name string or None Specified C name of type object
2595 # in_pxd boolean Is in a .pxd file
2596 # decorators [DecoratorNode] list of decorators or None
2597 # doc string or None
2598 # body StatNode or None
2599 # entry Symtab.Entry
2600 # base_type PyExtensionType or None
2601 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2602 # buffer_defaults_pos
2604 child_attrs = ["body"]
2605 buffer_defaults_node = None
2606 buffer_defaults_pos = None
2607 typedef_flag = False
2608 api = False
2609 objstruct_name = None
2610 typeobj_name = None
2611 decorators = None
2613 def analyse_declarations(self, env):
2614 #print "CClassDefNode.analyse_declarations:", self.class_name
2615 #print "...visibility =", self.visibility
2616 #print "...module_name =", self.module_name
2618 import Buffer
2619 if self.buffer_defaults_node:
2620 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2621 env, [], self.buffer_defaults_node,
2622 need_complete=False)
2623 else:
2624 buffer_defaults = None
2626 if env.in_cinclude and not self.objstruct_name:
2627 error(self.pos, "Object struct name specification required for "
2628 "C class defined in 'extern from' block")
2629 self.base_type = None
2630 # Now that module imports are cached, we need to
2631 # import the modules for extern classes.
2632 if self.module_name:
2633 self.module = None
2634 for module in env.cimported_modules:
2635 if module.name == self.module_name:
2636 self.module = module
2637 if self.module is None:
2638 self.module = ModuleScope(self.module_name, None, env.context)
2639 self.module.has_extern_class = 1
2640 env.add_imported_module(self.module)
2642 if self.base_class_name:
2643 if self.base_class_module:
2644 base_class_scope = env.find_module(self.base_class_module, self.pos)
2645 else:
2646 base_class_scope = env
2647 if self.base_class_name == 'object':
2648 # extension classes are special and don't need to inherit from object
2649 if base_class_scope is None or base_class_scope.lookup('object') is None:
2650 self.base_class_name = None
2651 self.base_class_module = None
2652 base_class_scope = None
2653 if base_class_scope:
2654 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2655 if base_class_entry:
2656 if not base_class_entry.is_type:
2657 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2658 elif not base_class_entry.type.is_extension_type:
2659 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2660 elif not base_class_entry.type.is_complete():
2661 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2662 else:
2663 self.base_type = base_class_entry.type
2664 has_body = self.body is not None
2665 if self.module_name and self.visibility != 'extern':
2666 module_path = self.module_name.split(".")
2667 home_scope = env.find_imported_module(module_path, self.pos)
2668 if not home_scope:
2669 return
2670 else:
2671 home_scope = env
2673 if self.visibility == 'extern':
2674 if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
2675 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
2677 self.entry = home_scope.declare_c_class(
2678 name = self.class_name,
2679 pos = self.pos,
2680 defining = has_body and self.in_pxd,
2681 implementing = has_body and not self.in_pxd,
2682 module_name = self.module_name,
2683 base_type = self.base_type,
2684 objstruct_cname = self.objstruct_name,
2685 typeobj_cname = self.typeobj_name,
2686 visibility = self.visibility,
2687 typedef_flag = self.typedef_flag,
2688 api = self.api,
2689 buffer_defaults = buffer_defaults)
2690 if home_scope is not env and self.visibility == 'extern':
2691 env.add_imported_entry(self.class_name, self.entry, pos)
2692 scope = self.entry.type.scope
2693 if scope is not None:
2694 scope.directives = env.directives
2696 if self.doc and Options.docstrings:
2697 scope.doc = embed_position(self.pos, self.doc)
2699 if has_body:
2700 self.body.analyse_declarations(scope)
2701 if self.in_pxd:
2702 scope.defined = 1
2703 else:
2704 scope.implemented = 1
2705 env.allocate_vtable_names(self.entry)
2707 def analyse_expressions(self, env):
2708 if self.body:
2709 scope = self.entry.type.scope
2710 self.body.analyse_expressions(scope)
2712 def generate_function_definitions(self, env, code):
2713 if self.body:
2714 self.body.generate_function_definitions(
2715 self.entry.type.scope, code)
2717 def generate_execution_code(self, code):
2718 # This is needed to generate evaluation code for
2719 # default values of method arguments.
2720 if self.body:
2721 self.body.generate_execution_code(code)
2723 def annotate(self, code):
2724 if self.body:
2725 self.body.annotate(code)
2728 class PropertyNode(StatNode):
2729 # Definition of a property in an extension type.
2730 #
2731 # name string
2732 # doc EncodedString or None Doc string
2733 # body StatListNode
2735 child_attrs = ["body"]
2737 def analyse_declarations(self, env):
2738 entry = env.declare_property(self.name, self.doc, self.pos)
2739 if entry:
2740 entry.scope.directives = env.directives
2741 self.body.analyse_declarations(entry.scope)
2743 def analyse_expressions(self, env):
2744 self.body.analyse_expressions(env)
2746 def generate_function_definitions(self, env, code):
2747 self.body.generate_function_definitions(env, code)
2749 def generate_execution_code(self, code):
2750 pass
2752 def annotate(self, code):
2753 self.body.annotate(code)
2756 class GlobalNode(StatNode):
2757 # Global variable declaration.
2758 #
2759 # names [string]
2761 child_attrs = []
2763 def analyse_declarations(self, env):
2764 for name in self.names:
2765 env.declare_global(name, self.pos)
2767 def analyse_expressions(self, env):
2768 pass
2770 def generate_execution_code(self, code):
2771 pass
2774 class ExprStatNode(StatNode):
2775 # Expression used as a statement.
2776 #
2777 # expr ExprNode
2779 child_attrs = ["expr"]
2781 def analyse_declarations(self, env):
2782 import ExprNodes
2783 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2784 func = self.expr.function.as_cython_attribute()
2785 if func == u'declare':
2786 args, kwds = self.expr.explicit_args_kwds()
2787 if len(args):
2788 error(self.expr.pos, "Variable names must be specified.")
2789 for var, type_node in kwds.key_value_pairs:
2790 type = type_node.analyse_as_type(env)
2791 if type is None:
2792 error(type_node.pos, "Unknown type")
2793 else:
2794 env.declare_var(var.value, type, var.pos, is_cdef = True)
2795 self.__class__ = PassStatNode
2797 def analyse_expressions(self, env):
2798 self.expr.analyse_expressions(env)
2800 def generate_execution_code(self, code):
2801 self.expr.generate_evaluation_code(code)
2802 if not self.expr.is_temp and self.expr.result():
2803 code.putln("%s;" % self.expr.result())
2804 self.expr.generate_disposal_code(code)
2805 self.expr.free_temps(code)
2807 def annotate(self, code):
2808 self.expr.annotate(code)
2811 class AssignmentNode(StatNode):
2812 # Abstract base class for assignment nodes.
2813 #
2814 # The analyse_expressions and generate_execution_code
2815 # phases of assignments are split into two sub-phases
2816 # each, to enable all the right hand sides of a
2817 # parallel assignment to be evaluated before assigning
2818 # to any of the left hand sides.
2820 def analyse_expressions(self, env):
2821 self.analyse_types(env)
2823 # def analyse_expressions(self, env):
2824 # self.analyse_expressions_1(env)
2825 # self.analyse_expressions_2(env)
2827 def generate_execution_code(self, code):
2828 self.generate_rhs_evaluation_code(code)
2829 self.generate_assignment_code(code)
2832 class SingleAssignmentNode(AssignmentNode):
2833 # The simplest case:
2834 #
2835 # a = b
2836 #
2837 # lhs ExprNode Left hand side
2838 # rhs ExprNode Right hand side
2839 # first bool Is this guaranteed the first assignment to lhs?
2841 child_attrs = ["lhs", "rhs"]
2842 first = False
2843 declaration_only = False
2845 def analyse_declarations(self, env):
2846 import ExprNodes
2848 # handle declarations of the form x = cython.foo()
2849 if isinstance(self.rhs, ExprNodes.CallNode):
2850 func_name = self.rhs.function.as_cython_attribute()
2851 if func_name:
2852 args, kwds = self.rhs.explicit_args_kwds()
2854 if func_name in ['declare', 'typedef']:
2855 if len(args) > 2 or kwds is not None:
2856 error(rhs.pos, "Can only declare one type at a time.")
2857 return
2858 type = args[0].analyse_as_type(env)
2859 if type is None:
2860 error(args[0].pos, "Unknown type")
2861 return
2862 lhs = self.lhs
2863 if func_name == 'declare':
2864 if isinstance(lhs, ExprNodes.NameNode):
2865 vars = [(lhs.name, lhs.pos)]
2866 elif isinstance(lhs, ExprNodes.TupleNode):
2867 vars = [(var.name, var.pos) for var in lhs.args]
2868 else:
2869 error(lhs.pos, "Invalid declaration")
2870 return
2871 for var, pos in vars:
2872 env.declare_var(var, type, pos, is_cdef = True)
2873 if len(args) == 2:
2874 # we have a value
2875 self.rhs = args[1]
2876 else:
2877 self.declaration_only = True
2878 else:
2879 self.declaration_only = True
2880 if not isinstance(lhs, ExprNodes.NameNode):
2881 error(lhs.pos, "Invalid declaration.")
2882 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2884 elif func_name in ['struct', 'union']:
2885 self.declaration_only = True
2886 if len(args) > 0 or kwds is None:
2887 error(rhs.pos, "Struct or union members must be given by name.")
2888 return
2889 members = []
2890 for member, type_node in kwds.key_value_pairs:
2891 type = type_node.analyse_as_type(env)
2892 if type is None:
2893 error(type_node.pos, "Unknown type")
2894 else:
2895 members.append((member.value, type, member.pos))
2896 if len(members) < len(kwds.key_value_pairs):
2897 return
2898 if not isinstance(self.lhs, ExprNodes.NameNode):
2899 error(self.lhs.pos, "Invalid declaration.")
2900 name = self.lhs.name
2901 scope = StructOrUnionScope(name)
2902 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2903 for member, type, pos in members:
2904 scope.declare_var(member, type, pos)
2906 if self.declaration_only:
2907 return
2908 else:
2909 self.lhs.analyse_target_declaration(env)
2911 def analyse_types(self, env, use_temp = 0):
2912 self.rhs.analyse_types(env)
2913 self.lhs.analyse_target_types(env)
2914 self.lhs.gil_assignment_check(env)
2915 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2916 if use_temp:
2917 self.rhs = self.rhs.coerce_to_temp(env)
2919 def generate_rhs_evaluation_code(self, code):
2920 self.rhs.generate_evaluation_code(code)
2922 def generate_assignment_code(self, code):
2923 self.lhs.generate_assignment_code(self.rhs, code)
2925 def annotate(self, code):
2926 self.lhs.annotate(code)
2927 self.rhs.annotate(code)
2930 class CascadedAssignmentNode(AssignmentNode):
2931 # An assignment with multiple left hand sides:
2932 #
2933 # a = b = c
2934 #
2935 # lhs_list [ExprNode] Left hand sides
2936 # rhs ExprNode Right hand sides
2937 #
2938 # Used internally:
2939 #
2940 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2942 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2943 coerced_rhs_list = None
2945 def analyse_declarations(self, env):
2946 for lhs in self.lhs_list:
2947 lhs.analyse_target_declaration(env)
2949 def analyse_types(self, env, use_temp = 0):
2950 self.rhs.analyse_types(env)
2951 if use_temp:
2952 self.rhs = self.rhs.coerce_to_temp(env)
2953 else:
2954 self.rhs = self.rhs.coerce_to_simple(env)
2955 from ExprNodes import CloneNode
2956 self.coerced_rhs_list = []
2957 for lhs in self.lhs_list:
2958 lhs.analyse_target_types(env)
2959 lhs.gil_assignment_check(env)
2960 rhs = CloneNode(self.rhs)
2961 rhs = rhs.coerce_to(lhs.type, env)
2962 self.coerced_rhs_list.append(rhs)
2964 def generate_rhs_evaluation_code(self, code):
2965 self.rhs.generate_evaluation_code(code)
2967 def generate_assignment_code(self, code):
2968 for i in range(len(self.lhs_list)):
2969 lhs = self.lhs_list[i]
2970 rhs = self.coerced_rhs_list[i]
2971 rhs.generate_evaluation_code(code)
2972 lhs.generate_assignment_code(rhs, code)
2973 # Assignment has disposed of the cloned RHS
2974 self.rhs.generate_disposal_code(code)
2975 self.rhs.free_temps(code)
2977 def annotate(self, code):
2978 for i in range(len(self.lhs_list)):
2979 lhs = self.lhs_list[i].annotate(code)
2980 rhs = self.coerced_rhs_list[i].annotate(code)
2981 self.rhs.annotate(code)
2984 class ParallelAssignmentNode(AssignmentNode):
2985 # A combined packing/unpacking assignment:
2986 #
2987 # a, b, c = d, e, f
2988 #
2989 # This has been rearranged by the parser into
2990 #
2991 # a = d ; b = e ; c = f
2992 #
2993 # but we must evaluate all the right hand sides
2994 # before assigning to any of the left hand sides.
2995 #
2996 # stats [AssignmentNode] The constituent assignments
2998 child_attrs = ["stats"]
3000 def analyse_declarations(self, env):
3001 for stat in self.stats:
3002 stat.analyse_declarations(env)
3004 def analyse_expressions(self, env):
3005 for stat in self.stats:
3006 stat.analyse_types(env, use_temp = 1)
3008 # def analyse_expressions(self, env):
3009 # for stat in self.stats:
3010 # stat.analyse_expressions_1(env, use_temp = 1)
3011 # for stat in self.stats:
3012 # stat.analyse_expressions_2(env)
3014 def generate_execution_code(self, code):
3015 for stat in self.stats:
3016 stat.generate_rhs_evaluation_code(code)
3017 for stat in self.stats:
3018 stat.generate_assignment_code(code)
3020 def annotate(self, code):
3021 for stat in self.stats:
3022 stat.annotate(code)
3025 class InPlaceAssignmentNode(AssignmentNode):
3026 # An in place arithmatic operand:
3027 #
3028 # a += b
3029 # a -= b
3030 # ...
3031 #
3032 # lhs ExprNode Left hand side
3033 # rhs ExprNode Right hand side
3034 # op char one of "+-*/%^&|"
3035 # dup (ExprNode) copy of lhs used for operation (auto-generated)
3036 #
3037 # This code is a bit tricky because in order to obey Python
3038 # semantics the sub-expressions (e.g. indices) of the lhs must
3039 # not be evaluated twice. So we must re-use the values calculated
3040 # in evaluation phase for the assignment phase as well.
3041 # Fortunately, the type of the lhs node is fairly constrained
3042 # (it must be a NameNode, AttributeNode, or IndexNode).
3044 child_attrs = ["lhs", "rhs"]
3045 dup = None
3047 def analyse_declarations(self, env):
3048 self.lhs.analyse_target_declaration(env)
3050 def analyse_types(self, env):
3051 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
3052 self.rhs.analyse_types(env)
3053 self.lhs.analyse_target_types(env)
3054 if Options.incref_local_binop and self.dup.type.is_pyobject:
3055 self.dup = self.dup.coerce_to_temp(env)
3056 import ExprNodes
3057 if self.lhs.type.is_pyobject:
3058 self.rhs = self.rhs.coerce_to_pyobject(env)
3059 elif self.rhs.type.is_pyobject:
3060 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
3061 if self.lhs.type.is_pyobject:
3062 self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
3063 self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
3065 def generate_execution_code(self, code):
3066 import ExprNodes
3067 self.rhs.generate_evaluation_code(code)
3068 self.dup.generate_subexpr_evaluation_code(code)
3069 if self.dup.is_temp:
3070 self.dup.allocate_temp_result(code)
3071 # self.dup.generate_result_code is run only if it is not buffer access
3072 if self.operator == "**":
3073 extra = ", Py_None"
3074 else:
3075 extra = ""
3076 if self.lhs.type.is_pyobject:
3077 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3078 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3079 self.dup.generate_result_code(code)
3080 self.result_value_temp.allocate(code)
3081 code.putln(
3082 "%s = %s(%s, %s%s); %s" % (
3083 self.result_value.result(),
3084 self.py_operation_function(),
3085 self.dup.py_result(),
3086 self.rhs.py_result(),
3087 extra,
3088 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3089 code.put_gotref(self.result_value.py_result())
3090 self.result_value.generate_evaluation_code(code) # May be a type check...
3091 self.rhs.generate_disposal_code(code)
3092 self.rhs.free_temps(code)
3093 self.dup.generate_disposal_code(code)
3094 self.dup.free_temps(code)
3095 self.lhs.generate_assignment_code(self.result_value, code)
3096 self.result_value_temp.release(code)
3097 else:
3098 c_op = self.operator
3099 if c_op == "//":
3100 c_op = "/"
3101 elif c_op == "**":
3102 error(self.pos, "No C inplace power operator")
3103 elif self.lhs.type.is_complex and not code.globalstate.directives['c99_complex']:
3104 error(self.pos, "Inplace operators not implemented for complex types.")
3106 # have to do assignment directly to avoid side-effects
3107 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3108 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3109 else:
3110 self.dup.generate_result_code(code)
3111 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3112 self.rhs.generate_disposal_code(code)
3113 self.rhs.free_temps(code)
3114 if self.dup.is_temp:
3115 self.dup.generate_subexpr_disposal_code(code)
3116 self.dup.free_subexpr_temps(code)
3118 def create_dup_node(self, env):
3119 import ExprNodes
3120 self.dup = self.lhs
3121 self.dup.analyse_types(env)
3122 if isinstance(self.lhs, ExprNodes.NameNode):
3123 target_lhs = ExprNodes.NameNode(self.dup.pos,
3124 name = self.dup.name,
3125 is_temp = self.dup.is_temp,
3126 entry = self.dup.entry)
3127 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3128 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3129 obj = ExprNodes.CloneNode(self.lhs.obj),
3130 attribute = self.dup.attribute,
3131 is_temp = self.dup.is_temp)
3132 elif isinstance(self.lhs, ExprNodes.IndexNode):
3133 if self.lhs.index:
3134 index = ExprNodes.CloneNode(self.lhs.index)
3135 else:
3136 index = None
3137 if self.lhs.indices:
3138 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3139 else:
3140 indices = []
3141 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3142 base = ExprNodes.CloneNode(self.dup.base),
3143 index = index,
3144 indices = indices,
3145 is_temp = self.dup.is_temp)
3146 else:
3147 assert False
3148 self.lhs = target_lhs
3149 return self.dup
3151 def py_operation_function(self):
3152 return self.py_functions[self.operator]
3154 py_functions = {
3155 "|": "PyNumber_InPlaceOr",
3156 "^": "PyNumber_InPlaceXor",
3157 "&": "PyNumber_InPlaceAnd",
3158 "+": "PyNumber_InPlaceAdd",
3159 "-": "PyNumber_InPlaceSubtract",
3160 "*": "PyNumber_InPlaceMultiply",
3161 "/": "PyNumber_InPlaceDivide",
3162 "%": "PyNumber_InPlaceRemainder",
3163 "<<": "PyNumber_InPlaceLshift",
3164 ">>": "PyNumber_InPlaceRshift",
3165 "**": "PyNumber_InPlacePower",
3166 "//": "PyNumber_InPlaceFloorDivide",
3167 }
3169 def annotate(self, code):
3170 self.lhs.annotate(code)
3171 self.rhs.annotate(code)
3172 self.dup.annotate(code)
3175 class PrintStatNode(StatNode):
3176 # print statement
3177 #
3178 # arg_tuple TupleNode
3179 # append_newline boolean
3181 child_attrs = ["arg_tuple"]
3183 def analyse_expressions(self, env):
3184 self.arg_tuple.analyse_expressions(env)
3185 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3186 env.use_utility_code(printing_utility_code)
3187 if len(self.arg_tuple.args) == 1 and self.append_newline:
3188 env.use_utility_code(printing_one_utility_code)
3190 nogil_check = Node.gil_error
3191 gil_message = "Python print statement"
3193 def generate_execution_code(self, code):
3194 if len(self.arg_tuple.args) == 1 and self.append_newline:
3195 arg = self.arg_tuple.args[0]
3196 arg.generate_evaluation_code(code)
3198 code.putln(
3199 "if (__Pyx_PrintOne(%s) < 0) %s" % (
3200 arg.py_result(),
3201 code.error_goto(self.pos)))
3202 arg.generate_disposal_code(code)
3203 arg.free_temps(code)
3204 else:
3205 self.arg_tuple.generate_evaluation_code(code)
3206 code.putln(
3207 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3208 self.arg_tuple.py_result(),
3209 self.append_newline,
3210 code.error_goto(self.pos)))
3211 self.arg_tuple.generate_disposal_code(code)
3212 self.arg_tuple.free_temps(code)
3214 def annotate(self, code):
3215 self.arg_tuple.annotate(code)
3218 class ExecStatNode(StatNode):
3219 # exec statement
3220 #
3221 # args [ExprNode]
3223 child_attrs = ["args"]
3225 def analyse_expressions(self, env):
3226 for i, arg in enumerate(self.args):
3227 arg.analyse_expressions(env)
3228 arg = arg.coerce_to_pyobject(env)
3229 self.args[i] = arg
3230 env.use_utility_code(Builtin.pyexec_utility_code)
3232 nogil_check = Node.gil_error
3233 gil_message = "Python exec statement"
3235 def generate_execution_code(self, code):
3236 args = []
3237 for arg in self.args:
3238 arg.generate_evaluation_code(code)
3239 args.append( arg.py_result() )
3240 args = tuple(args + ['0', '0'][:3-len(args)])
3241 temp_result = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
3242 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3243 (temp_result,) + args))
3244 for arg in self.args:
3245 arg.generate_disposal_code(code)
3246 arg.free_temps(code)
3247 code.putln(
3248 code.error_goto_if_null(temp_result, self.pos))
3249 code.put_gotref(temp_result)
3250 code.put_decref_clear(temp_result, py_object_type)
3251 code.funcstate.release_temp(temp_result)
3253 def annotate(self, code):
3254 for arg in self.args:
3255 arg.annotate(code)
3258 class DelStatNode(StatNode):
3259 # del statement
3260 #
3261 # args [ExprNode]
3263 child_attrs = ["args"]
3265 def analyse_declarations(self, env):
3266 for arg in self.args:
3267 arg.analyse_target_declaration(env)
3269 def analyse_expressions(self, env):
3270 for arg in self.args:
3271 arg.analyse_target_expression(env, None)
3272 if not arg.type.is_pyobject:
3273 error(arg.pos, "Deletion of non-Python object")
3274 #arg.release_target_temp(env)
3276 def nogil_check(self, env):
3277 for arg in self.args:
3278 if arg.type.is_pyobject:
3279 self.gil_error()
3281 gil_message = "Deleting Python object"
3283 def generate_execution_code(self, code):
3284 for arg in self.args:
3285 if arg.type.is_pyobject:
3286 arg.generate_deletion_code(code)
3287 # else error reported earlier
3289 def annotate(self, code):
3290 for arg in self.args:
3291 arg.annotate(code)
3294 class PassStatNode(StatNode):
3295 # pass statement
3297 child_attrs = []
3299 def analyse_expressions(self, env):
3300 pass
3302 def generate_execution_code(self, code):
3303 pass
3306 class BreakStatNode(StatNode):
3308 child_attrs = []
3310 def analyse_expressions(self, env):
3311 pass
3313 def generate_execution_code(self, code):
3314 if not code.break_label:
3315 error(self.pos, "break statement not inside loop")
3316 else:
3317 code.put_goto(code.break_label)
3320 class ContinueStatNode(StatNode):
3322 child_attrs = []
3324 def analyse_expressions(self, env):
3325 pass
3327 def generate_execution_code(self, code):
3328 if code.funcstate.in_try_finally:
3329 error(self.pos, "continue statement inside try of try...finally")
3330 elif not code.continue_label:
3331 error(self.pos, "continue statement not inside loop")
3332 else:
3333 code.put_goto(code.continue_label)
3336 class ReturnStatNode(StatNode):
3337 # return statement
3338 #
3339 # value ExprNode or None
3340 # return_type PyrexType
3342 child_attrs = ["value"]
3344 def analyse_expressions(self, env):
3345 return_type = env.return_type
3346 self.return_type = return_type
3347 if not return_type:
3348 error(self.pos, "Return not inside a function body")
3349 return
3350 if self.value:
3351 self.value.analyse_types(env)
3352 if return_type.is_void or return_type.is_returncode:
3353 error(self.value.pos,
3354 "Return with value in void function")
3355 else:
3356 self.value = self.value.coerce_to(env.return_type, env)
3357 else:
3358 if (not return_type.is_void
3359 and not return_type.is_pyobject
3360 and not return_type.is_returncode):
3361 error(self.pos, "Return value required")
3363 def nogil_check(self, env):
3364 if self.return_type.is_pyobject:
3365 self.gil_error()
3367 gil_message = "Returning Python object"
3369 def generate_execution_code(self, code):
3370 code.mark_pos(self.pos)
3371 if not self.return_type:
3372 # error reported earlier
3373 return
3374 if self.return_type.is_pyobject:
3375 code.put_xdecref(Naming.retval_cname,
3376 self.return_type)
3377 if self.value:
3378 self.value.generate_evaluation_code(code)
3379 self.value.make_owned_reference(code)
3380 code.putln(
3381 "%s = %s;" % (
3382 Naming.retval_cname,
3383 self.value.result_as(self.return_type)))
3384 self.value.generate_post_assignment_code(code)
3385 self.value.free_temps(code)
3386 else:
3387 if self.return_type.is_pyobject:
3388 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3389 elif self.return_type.is_returncode:
3390 code.putln(
3391 "%s = %s;" % (
3392 Naming.retval_cname,
3393 self.return_type.default_value))
3394 for cname, type in code.funcstate.temps_holding_reference():
3395 code.put_decref_clear(cname, type)
3396 code.put_goto(code.return_label)
3398 def annotate(self, code):
3399 if self.value:
3400 self.value.annotate(code)
3403 class RaiseStatNode(StatNode):
3404 # raise statement
3405 #
3406 # exc_type ExprNode or None
3407 # exc_value ExprNode or None
3408 # exc_tb ExprNode or None
3410 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3412 def analyse_expressions(self, env):
3413 if self.exc_type:
3414 self.exc_type.analyse_types(env)
3415 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3416 if self.exc_value:
3417 self.exc_value.analyse_types(env)
3418 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3419 if self.exc_tb:
3420 self.exc_tb.analyse_types(env)
3421 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3422 env.use_utility_code(raise_utility_code)
3423 env.use_utility_code(restore_exception_utility_code)
3425 nogil_check = Node.gil_error
3426 gil_message = "Raising exception"
3428 def generate_execution_code(self, code):
3429 if self.exc_type:
3430 self.exc_type.generate_evaluation_code(code)
3431 type_code = self.exc_type.py_result()
3432 else:
3433 type_code = "0"
3434 if self.exc_value:
3435 self.exc_value.generate_evaluation_code(code)
3436 value_code = self.exc_value.py_result()
3437 else:
3438 value_code = "0"
3439 if self.exc_tb:
3440 self.exc_tb.generate_evaluation_code(code)
3441 tb_code = self.exc_tb.py_result()
3442 else:
3443 tb_code = "0"
3444 if self.exc_type or self.exc_value or self.exc_tb:
3445 code.putln(
3446 "__Pyx_Raise(%s, %s, %s);" % (
3447 type_code,
3448 value_code,
3449 tb_code))
3450 else:
3451 code.putln(
3452 "__Pyx_ReRaise();")
3453 for obj in (self.exc_type, self.exc_value, self.exc_tb):
3454 if obj:
3455 obj.generate_disposal_code(code)
3456 obj.free_temps(code)
3457 code.putln(
3458 code.error_goto(self.pos))
3460 def annotate(self, code):
3461 if self.exc_type:
3462 self.exc_type.annotate(code)
3463 if self.exc_value:
3464 self.exc_value.annotate(code)
3465 if self.exc_tb:
3466 self.exc_tb.annotate(code)
3469 class ReraiseStatNode(StatNode):
3471 child_attrs = []
3473 def analyse_expressions(self, env):
3474 env.use_utility_code(raise_utility_code)
3475 env.use_utility_code(restore_exception_utility_code)
3477 nogil_check = Node.gil_error
3478 gil_message = "Raising exception"
3480 def generate_execution_code(self, code):
3481 vars = code.funcstate.exc_vars
3482 if vars:
3483 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3484 code.putln(code.error_goto(self.pos))
3485 else:
3486 error(self.pos, "Reraise not inside except clause")
3489 class AssertStatNode(StatNode):
3490 # assert statement
3491 #
3492 # cond ExprNode
3493 # value ExprNode or None
3495 child_attrs = ["cond", "value"]
3497 def analyse_expressions(self, env):
3498 self.cond = self.cond.analyse_boolean_expression(env)
3499 if self.value:
3500 self.value.analyse_types(env)
3501 self.value = self.value.coerce_to_pyobject(env)
3503 nogil_check = Node.gil_error
3504 gil_message = "Raising exception"
3506 def generate_execution_code(self, code):
3507 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3508 self.cond.generate_evaluation_code(code)
3509 code.putln(
3510 "if (unlikely(!%s)) {" %
3511 self.cond.result())
3512 if self.value:
3513 self.value.generate_evaluation_code(code)
3514 code.putln(
3515 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3516 self.value.py_result())
3517 self.value.generate_disposal_code(code)
3518 self.value.free_temps(code)
3519 else:
3520 code.putln(
3521 "PyErr_SetNone(PyExc_AssertionError);")
3522 code.putln(
3523 code.error_goto(self.pos))
3524 code.putln(
3525 "}")
3526 self.cond.generate_disposal_code(code)
3527 self.cond.free_temps(code)
3528 code.putln("#endif")
3530 def annotate(self, code):
3531 self.cond.annotate(code)
3532 if self.value:
3533 self.value.annotate(code)
3536 class IfStatNode(StatNode):
3537 # if statement
3538 #
3539 # if_clauses [IfClauseNode]
3540 # else_clause StatNode or None
3542 child_attrs = ["if_clauses", "else_clause"]
3544 def analyse_control_flow(self, env):
3545 env.start_branching(self.pos)
3546 for if_clause in self.if_clauses:
3547 if_clause.analyse_control_flow(env)
3548 env.next_branch(if_clause.end_pos())
3549 if self.else_clause:
3550 self.else_clause.analyse_control_flow(env)
3551 env.finish_branching(self.end_pos())
3553 def analyse_declarations(self, env):
3554 for if_clause in self.if_clauses:
3555 if_clause.analyse_declarations(env)
3556 if self.else_clause:
3557 self.else_clause.analyse_declarations(env)
3559 def analyse_expressions(self, env):
3560 for if_clause in self.if_clauses:
3561 if_clause.analyse_expressions(env)
3562 if self.else_clause:
3563 self.else_clause.analyse_expressions(env)
3565 def generate_execution_code(self, code):
3566 code.mark_pos(self.pos)
3567 end_label = code.new_label()
3568 for if_clause in self.if_clauses:
3569 if_clause.generate_execution_code(code, end_label)
3570 if self.else_clause:
3571 code.putln("/*else*/ {")
3572 self.else_clause.generate_execution_code(code)
3573 code.putln("}")
3574 code.put_label(end_label)
3576 def annotate(self, code):
3577 for if_clause in self.if_clauses:
3578 if_clause.annotate(code)
3579 if self.else_clause:
3580 self.else_clause.annotate(code)
3583 class IfClauseNode(Node):
3584 # if or elif clause in an if statement
3585 #
3586 # condition ExprNode
3587 # body StatNode
3589 child_attrs = ["condition", "body"]
3591 def analyse_control_flow(self, env):
3592 self.body.analyse_control_flow(env)
3594 def analyse_declarations(self, env):
3595 self.condition.analyse_declarations(env)
3596 self.body.analyse_declarations(env)
3598 def analyse_expressions(self, env):
3599 self.condition = \
3600 self.condition.analyse_temp_boolean_expression(env)
3601 self.body.analyse_expressions(env)
3603 def generate_execution_code(self, code, end_label):
3604 self.condition.generate_evaluation_code(code)
3605 code.putln(
3606 "if (%s) {" %
3607 self.condition.result())
3608 self.condition.generate_disposal_code(code)
3609 self.condition.free_temps(code)
3610 self.body.generate_execution_code(code)
3611 #code.putln(
3612 # "goto %s;" %
3613 # end_label)
3614 code.put_goto(end_label)
3615 code.putln("}")
3617 def annotate(self, code):
3618 self.condition.annotate(code)
3619 self.body.annotate(code)
3622 class SwitchCaseNode(StatNode):
3623 # Generated in the optimization of an if-elif-else node
3624 #
3625 # conditions [ExprNode]
3626 # body StatNode
3628 child_attrs = ['conditions', 'body']
3630 def generate_execution_code(self, code):
3631 for cond in self.conditions:
3632 code.mark_pos(cond.pos)
3633 cond.generate_evaluation_code(code)
3634 code.putln("case %s:" % cond.result())
3635 self.body.generate_execution_code(code)
3636 code.putln("break;")
3638 def annotate(self, code):
3639 for cond in self.conditions:
3640 cond.annotate(code)
3641 self.body.annotate(code)
3643 class SwitchStatNode(StatNode):
3644 # Generated in the optimization of an if-elif-else node
3645 #
3646 # test ExprNode
3647 # cases [SwitchCaseNode]
3648 # else_clause StatNode or None
3650 child_attrs = ['test', 'cases', 'else_clause']
3652 def generate_execution_code(self, code):
3653 code.putln("switch (%s) {" % self.test.result())
3654 for case in self.cases:
3655 case.generate_execution_code(code)
3656 if self.else_clause is not None:
3657 code.putln("default:")
3658 self.else_clause.generate_execution_code(code)
3659 code.putln("break;")
3660 code.putln("}")
3662 def annotate(self, code):
3663 self.test.annotate(code)
3664 for case in self.cases:
3665 case.annotate(code)
3666 if self.else_clause is not None:
3667 self.else_clause.annotate(code)
3669 class LoopNode(object):
3671 def analyse_control_flow(self, env):
3672 env.start_branching(self.pos)
3673 self.body.analyse_control_flow(env)
3674 env.next_branch(self.body.end_pos())
3675 if self.else_clause:
3676 self.else_clause.analyse_control_flow(env)
3677 env.finish_branching(self.end_pos())
3680 class WhileStatNode(LoopNode, StatNode):
3681 # while statement
3682 #
3683 # condition ExprNode
3684 # body StatNode
3685 # else_clause StatNode
3687 child_attrs = ["condition", "body", "else_clause"]
3689 def analyse_declarations(self, env):
3690 self.body.analyse_declarations(env)
3691 if self.else_clause:
3692 self.else_clause.analyse_declarations(env)
3694 def analyse_expressions(self, env):
3695 self.condition = \
3696 self.condition.analyse_temp_boolean_expression(env)
3697 self.body.analyse_expressions(env)
3698 if self.else_clause:
3699 self.else_clause.analyse_expressions(env)
3701 def generate_execution_code(self, code):
3702 old_loop_labels = code.new_loop_labels()
3703 code.putln(
3704 "while (1) {")
3705 self.condition.generate_evaluation_code(code)
3706 self.condition.generate_disposal_code(code)
3707 code.putln(
3708 "if (!%s) break;" %
3709 self.condition.result())
3710 self.condition.free_temps(code)
3711 self.body.generate_execution_code(code)
3712 code.put_label(code.continue_label)
3713 code.putln("}")
3714 break_label = code.break_label
3715 code.set_loop_labels(old_loop_labels)
3716 if self.else_clause:
3717 code.putln("/*else*/ {")
3718 self.else_clause.generate_execution_code(code)
3719 code.putln("}")
3720 code.put_label(break_label)
3722 def annotate(self, code):
3723 self.condition.annotate(code)
3724 self.body.annotate(code)
3725 if self.else_clause:
3726 self.else_clause.annotate(code)
3729 def ForStatNode(pos, **kw):
3730 if 'iterator' in kw:
3731 return ForInStatNode(pos, **kw)
3732 else:
3733 return ForFromStatNode(pos, **kw)
3735 class ForInStatNode(LoopNode, StatNode):
3736 # for statement
3737 #
3738 # target ExprNode
3739 # iterator IteratorNode
3740 # body StatNode
3741 # else_clause StatNode
3742 # item NextNode used internally
3744 child_attrs = ["target", "iterator", "body", "else_clause"]
3745 item = None
3747 def analyse_declarations(self, env):
3748 self.target.analyse_target_declaration(env)
3749 self.body.analyse_declarations(env)
3750 if self.else_clause:
3751 self.else_clause.analyse_declarations(env)
3753 def analyse_expressions(self, env):
3754 import ExprNodes
3755 self.target.analyse_target_types(env)
3756 self.iterator.analyse_expressions(env)
3757 self.item = ExprNodes.NextNode(self.iterator, env)
3758 self.item = self.item.coerce_to(self.target.type, env)
3759 self.body.analyse_expressions(env)
3760 if self.else_clause:
3761 self.else_clause.analyse_expressions(env)
3763 def generate_execution_code(self, code):
3764 old_loop_labels = code.new_loop_labels()
3765 self.iterator.allocate_counter_temp(code)
3766 self.iterator.generate_evaluation_code(code)
3767 code.putln(
3768 "for (;;) {")
3769 self.item.generate_evaluation_code(code)
3770 self.target.generate_assignment_code(self.item, code)
3771 self.body.generate_execution_code(code)
3772 code.put_label(code.continue_label)
3773 code.putln(
3774 "}")
3775 break_label = code.break_label
3776 code.set_loop_labels(old_loop_labels)
3777 if self.else_clause:
3778 code.putln("/*else*/ {")
3779 self.else_clause.generate_execution_code(code)
3780 code.putln("}")
3781 code.put_label(break_label)
3782 self.iterator.release_counter_temp(code)
3783 self.iterator.generate_disposal_code(code)
3784 self.iterator.free_temps(code)
3786 def annotate(self, code):
3787 self.target.annotate(code)
3788 self.iterator.annotate(code)
3789 self.body.annotate(code)
3790 if self.else_clause:
3791 self.else_clause.annotate(code)
3792 self.item.annotate(code)
3795 class ForFromStatNode(LoopNode, StatNode):
3796 # for name from expr rel name rel expr
3797 #
3798 # target NameNode
3799 # bound1 ExprNode
3800 # relation1 string
3801 # relation2 string
3802 # bound2 ExprNode
3803 # step ExprNode or None
3804 # body StatNode
3805 # else_clause StatNode or None
3806 #
3807 # Used internally:
3808 #
3809 # from_range bool
3810 # is_py_target bool
3811 # loopvar_node ExprNode (usually a NameNode or temp node)
3812 # py_loopvar_node PyTempNode or None
3813 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3815 is_py_target = False
3816 loopvar_node = None
3817 py_loopvar_node = None
3818 from_range = False
3820 gil_message = "For-loop using object bounds or target"
3822 def nogil_check(self, env):
3823 for x in (self.target, self.bound1, self.bound2):
3824 if x.type.is_pyobject:
3825 self.gil_error()
3827 def analyse_declarations(self, env):
3828 self.target.analyse_target_declaration(env)
3829 self.body.analyse_declarations(env)
3830 if self.else_clause:
3831 self.else_clause.analyse_declarations(env)
3833 def analyse_expressions(self, env):
3834 import ExprNodes
3835 self.target.analyse_target_types(env)
3836 self.bound1.analyse_types(env)
3837 self.bound2.analyse_types(env)
3838 if self.step is not None:
3839 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3840 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3841 self.step.analyse_types(env)
3843 target_type = self.target.type
3844 if self.target.type.is_numeric:
3845 loop_type = self.target.type
3846 else:
3847 loop_type = PyrexTypes.c_int_type
3848 if not self.bound1.type.is_pyobject:
3849 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound1.type)
3850 if not self.bound2.type.is_pyobject:
3851 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.bound2.type)
3852 if self.step is not None and not self.step.type.is_pyobject:
3853 loop_type = PyrexTypes.widest_numeric_type(loop_type, self.step.type)
3854 self.bound1 = self.bound1.coerce_to(loop_type, env)
3855 self.bound2 = self.bound2.coerce_to(loop_type, env)
3856 if not self.bound2.is_literal:
3857 self.bound2 = self.bound2.coerce_to_temp(env)
3858 if self.step is not None:
3859 self.step = self.step.coerce_to(loop_type, env)
3860 if not self.step.is_literal:
3861 self.step = self.step.coerce_to_temp(env)
3863 target_type = self.target.type
3864 if not (target_type.is_pyobject or target_type.is_numeric):
3865 error(self.target.pos,
3866 "for-from loop variable must be c numeric type or Python object")
3867 if target_type.is_numeric:
3868 self.is_py_target = False
3869 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3870 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3871 self.loopvar_node = self.target
3872 self.py_loopvar_node = None
3873 else:
3874 self.is_py_target = True
3875 c_loopvar_node = ExprNodes.TempNode(self.pos, loop_type, env)
3876 self.loopvar_node = c_loopvar_node
3877 self.py_loopvar_node = \
3878 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3879 self.body.analyse_expressions(env)
3880 if self.else_clause:
3881 self.else_clause.analyse_expressions(env)
3883 def generate_execution_code(self, code):
3884 old_loop_labels = code.new_loop_labels()
3885 from_range = self.from_range
3886 self.bound1.generate_evaluation_code(code)
3887 self.bound2.generate_evaluation_code(code)
3888 offset, incop = self.relation_table[self.relation1]
3889 if self.step is not None:
3890 self.step.generate_evaluation_code(code)
3891 step = self.step.result()
3892 incop = "%s=%s" % (incop[0], step)
3893 import ExprNodes
3894 if isinstance(self.loopvar_node, ExprNodes.TempNode):
3895 self.loopvar_node.allocate(code)
3896 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
3897 self.py_loopvar_node.allocate(code)
3898 if from_range:
3899 loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
3900 else:
3901 loopvar_name = self.loopvar_node.result()
3902 code.putln(
3903 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3904 loopvar_name,
3905 self.bound1.result(), offset,
3906 loopvar_name, self.relation2, self.bound2.result(),
3907 loopvar_name, incop))
3908 if self.py_loopvar_node:
3909 self.py_loopvar_node.generate_evaluation_code(code)
3910 self.target.generate_assignment_code(self.py_loopvar_node, code)
3911 elif from_range:
3912 code.putln("%s = %s;" % (
3913 self.target.result(), loopvar_name))
3914 self.body.generate_execution_code(code)
3915 code.put_label(code.continue_label)
3916 if self.py_loopvar_node:
3917 # This mess is to make for..from loops with python targets behave
3918 # exactly like those with C targets with regards to re-assignment
3919 # of the loop variable.
3920 import ExprNodes
3921 if self.target.entry.is_pyglobal:
3922 # We know target is a NameNode, this is the only ugly case.
3923 target_node = ExprNodes.PyTempNode(self.target.pos, None)
3924 target_node.allocate(code)
3925 interned_cname = code.intern_identifier(self.target.entry.name)
3926 code.putln("/*here*/")
3927 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
3928 target_node.result(),
3929 Naming.module_cname,
3930 interned_cname,
3931 code.error_goto_if_null(target_node.result(), self.target.pos)))
3932 code.put_gotref(target_node.result())
3933 else:
3934 target_node = self.target
3935 from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
3936 from_py_node.temp_code = loopvar_name
3937 from_py_node.generate_result_code(code)
3938 if self.target.entry.is_pyglobal:
3939 code.put_decref(target_node.result(), target_node.type)
3940 target_node.release(code)
3941 code.putln("}")
3942 if self.py_loopvar_node:
3943 # This is potentially wasteful, but we don't want the semantics to
3944 # depend on whether or not the loop is a python type.
3945 self.py_loopvar_node.generate_evaluation_code(code)
3946 self.target.generate_assignment_code(self.py_loopvar_node, code)
3947 break_label = code.break_label
3948 code.set_loop_labels(old_loop_labels)
3949 if self.else_clause:
3950 code.putln("/*else*/ {")
3951 self.else_clause.generate_execution_code(code)
3952 code.putln("}")
3953 code.put_label(break_label)
3954 self.bound1.generate_disposal_code(code)
3955 self.bound1.free_temps(code)
3956 self.bound2.generate_disposal_code(code)
3957 self.bound2.free_temps(code)
3958 if isinstance(self.loopvar_node, ExprNodes.TempNode):
3959 self.loopvar_node.release(code)
3960 if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
3961 self.py_loopvar_node.release(code)
3962 if self.step is not None:
3963 self.step.generate_disposal_code(code)
3964 self.step.free_temps(code)
3966 relation_table = {
3967 # {relop : (initial offset, increment op)}
3968 '<=': ("", "++"),
3969 '<' : ("+1", "++"),
3970 '>=': ("", "--"),
3971 '>' : ("-1", "--")
3972 }
3974 def annotate(self, code):
3975 self.target.annotate(code)
3976 self.bound1.annotate(code)
3977 self.bound2.annotate(code)
3978 if self.step:
3979 self.bound2.annotate(code)
3980 self.body.annotate(code)
3981 if self.else_clause:
3982 self.else_clause.annotate(code)
3985 class WithStatNode(StatNode):
3986 """
3987 Represents a Python with statement.
3989 This is only used at parse tree level; and is not present in
3990 analysis or generation phases.
3991 """
3992 # manager The with statement manager object
3993 # target Node (lhs expression)
3994 # body StatNode
3995 child_attrs = ["manager", "target", "body"]
3997 class TryExceptStatNode(StatNode):
3998 # try .. except statement
3999 #
4000 # body StatNode
4001 # except_clauses [ExceptClauseNode]
4002 # else_clause StatNode or None
4004 child_attrs = ["body", "except_clauses", "else_clause"]
4006 def analyse_control_flow(self, env):
4007 env.start_branching(self.pos)
4008 self.body.analyse_control_flow(env)
4009 successful_try = env.control_flow # grab this for later
4010 env.next_branch(self.body.end_pos())
4011 env.finish_branching(self.body.end_pos())
4013 env.start_branching(self.except_clauses[0].pos)
4014 for except_clause in self.except_clauses:
4015 except_clause.analyse_control_flow(env)
4016 env.next_branch(except_clause.end_pos())
4018 # the else cause it executed only when the try clause finishes
4019 env.control_flow.incoming = successful_try
4020 if self.else_clause:
4021 self.else_clause.analyse_control_flow(env)
4022 env.finish_branching(self.end_pos())
4024 def analyse_declarations(self, env):
4025 self.body.analyse_declarations(env)
4026 for except_clause in self.except_clauses:
4027 except_clause.analyse_declarations(env)
4028 if self.else_clause:
4029 self.else_clause.analyse_declarations(env)
4030 env.use_utility_code(reset_exception_utility_code)
4032 def analyse_expressions(self, env):
4033 self.body.analyse_expressions(env)
4034 default_clause_seen = 0
4035 for except_clause in self.except_clauses:
4036 except_clause.analyse_expressions(env)
4037 if default_clause_seen:
4038 error(except_clause.pos, "default 'except:' must be last")
4039 if not except_clause.pattern:
4040 default_clause_seen = 1
4041 self.has_default_clause = default_clause_seen
4042 if self.else_clause:
4043 self.else_clause.analyse_expressions(env)
4045 nogil_check = Node.gil_error
4046 gil_message = "Try-except statement"
4048 def generate_execution_code(self, code):
4049 old_return_label = code.return_label
4050 old_break_label = code.break_label
4051 old_continue_label = code.continue_label
4052 old_error_label = code.new_error_label()
4053 our_error_label = code.error_label
4054 except_end_label = code.new_label('exception_handled')
4055 except_error_label = code.new_label('except_error')
4056 except_return_label = code.new_label('except_return')
4057 try_return_label = code.new_label('try_return')
4058 try_break_label = code.new_label('try_break')
4059 try_continue_label = code.new_label('try_continue')
4060 try_end_label = code.new_label('try_end')
4062 code.putln("{")
4063 code.putln("PyObject %s;" %
4064 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
4065 code.putln("__Pyx_ExceptionSave(%s);" %
4066 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
4067 for var in Naming.exc_save_vars:
4068 code.put_xgotref(var)
4069 code.putln(
4070 "/*try:*/ {")
4071 code.return_label = try_return_label
4072 code.break_label = try_break_label
4073 code.continue_label = try_continue_label
4074 self.body.generate_execution_code(code)
4075 code.putln(
4076 "}")
4077 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4078 code.error_label = except_error_label
4079 code.return_label = except_return_label
4080 if self.else_clause:
4081 code.putln(
4082 "/*else:*/ {")
4083 self.else_clause.generate_execution_code(code)
4084 code.putln(
4085 "}")
4086 for var in Naming.exc_save_vars:
4087 code.put_xdecref_clear(var, py_object_type)
4088 code.put_goto(try_end_label)
4089 if code.label_used(try_return_label):
4090 code.put_label(try_return_label)
4091 for var in Naming.exc_save_vars:
4092 code.put_xdecref_clear(var, py_object_type)
4093 code.put_goto(old_return_label)
4094 code.put_label(our_error_label)
4095 for temp_name, type in temps_to_clean_up:
4096 code.put_xdecref_clear(temp_name, type)
4097 for except_clause in self.except_clauses:
4098 except_clause.generate_handling_code(code, except_end_label)
4100 error_label_used = code.label_used(except_error_label)
4101 if error_label_used or not self.has_default_clause:
4102 if error_label_used:
4103 code.put_label(except_error_label)
4104 for var in Naming.exc_save_vars:
4105 code.put_xdecref(var, py_object_type)
4106 code.put_goto(old_error_label)
4108 if code.label_used(try_break_label):
4109 code.put_label(try_break_label)
4110 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4111 code.putln("__Pyx_ExceptionReset(%s);" %
4112 ', '.join(Naming.exc_save_vars))
4113 code.put_goto(old_break_label)
4115 if code.label_used(try_continue_label):
4116 code.put_label(try_continue_label)
4117 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4118 code.putln("__Pyx_ExceptionReset(%s);" %
4119 ', '.join(Naming.exc_save_vars))
4120 code.put_goto(old_continue_label)
4122 if code.label_used(except_return_label):
4123 code.put_label(except_return_label)
4124 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4125 code.putln("__Pyx_ExceptionReset(%s);" %
4126 ', '.join(Naming.exc_save_vars))
4127 code.put_goto(old_return_label)
4129 if code.label_used(except_end_label):
4130 code.put_label(except_end_label)
4131 for var in Naming.exc_save_vars: code.put_xgiveref(var)
4132 code.putln("__Pyx_ExceptionReset(%s);" %
4133 ', '.join(Naming.exc_save_vars))
4134 code.put_label(try_end_label)
4135 code.putln("}")
4137 code.return_label = old_return_label
4138 code.break_label = old_break_label
4139 code.continue_label = old_continue_label
4140 code.error_label = old_error_label
4142 def annotate(self, code):
4143 self.body.annotate(code)
4144 for except_node in self.except_clauses:
4145 except_node.annotate(code)
4146 if self.else_clause:
4147 self.else_clause.annotate(code)
4150 class ExceptClauseNode(Node):
4151 # Part of try ... except statement.
4152 #
4153 # pattern ExprNode
4154 # target ExprNode or None
4155 # body StatNode
4156 # excinfo_target NameNode or None optional target for exception info
4157 # match_flag string result of exception match
4158 # exc_value ExcValueNode used internally
4159 # function_name string qualified name of enclosing function
4160 # exc_vars (string * 3) local exception variables
4162 # excinfo_target is never set by the parser, but can be set by a transform
4163 # in order to extract more extensive information about the exception as a
4164 # sys.exc_info()-style tuple into a target variable
4166 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4168 exc_value = None
4169 excinfo_target = None
4171 def analyse_declarations(self, env):
4172 if self.target:
4173 self.target.analyse_target_declaration(env)
4174 if self.excinfo_target is not None:
4175 self.excinfo_target.analyse_target_declaration(env)
4176 self.body.analyse_declarations(env)
4178 def analyse_expressions(self, env):
4179 import ExprNodes
4180 genv = env.global_scope()
4181 self.function_name = env.qualified_name
4182 if self.pattern:
4183 self.pattern.analyse_expressions(env)
4184 self.pattern = self.pattern.coerce_to_pyobject(env)
4186 if self.target:
4187 self.exc_value = ExprNodes.ExcValueNode(self.pos, env)
4188 self.target.analyse_target_expression(env, self.exc_value)
4189 if self.excinfo_target is not None:
4190 import ExprNodes
4191 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4192 ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)])
4193 self.excinfo_tuple.analyse_expressions(env)
4194 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4196 self.body.analyse_expressions(env)
4198 def generate_handling_code(self, code, end_label):
4199 code.mark_pos(self.pos)
4200 if self.pattern:
4201 self.pattern.generate_evaluation_code(code)
4203 match_flag = code.funcstate.allocate_temp(PyrexTypes.c_int_type, False)
4204 code.putln(
4205 "%s = PyErr_ExceptionMatches(%s);" % (
4206 match_flag,
4207 self.pattern.py_result()))
4208 self.pattern.generate_disposal_code(code)
4209 self.pattern.free_temps(code)
4210 code.putln(
4211 "if (%s) {" %
4212 match_flag)
4213 code.funcstate.release_temp(match_flag)
4214 else:
4215 code.putln("/*except:*/ {")
4217 if not getattr(self.body, 'stats', True):
4218 # most simple case: no exception variable, empty body (pass)
4219 # => reset the exception state, done
4220 code.putln("PyErr_Restore(0,0,0);")
4221 code.put_goto(end_label)
4222 code.putln("}")
4223 return
4225 exc_vars = [code.funcstate.allocate_temp(py_object_type,
4226 manage_ref=True)
4227 for i in xrange(3)]
4228 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4229 # We always have to fetch the exception value even if
4230 # there is no target, because this also normalises the
4231 # exception and stores it in the thread state.
4232 code.globalstate.use_utility_code(get_exception_utility_code)
4233 exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
4234 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4235 code.error_goto(self.pos)))
4236 for x in exc_vars:
4237 code.put_gotref(x)
4238 if self.target:
4239 self.exc_value.set_var(exc_vars[1])
4240 self.exc_value.generate_evaluation_code(code)
4241 self.target.generate_assignment_code(self.exc_value, code)
4242 if self.excinfo_target is not None:
4243 for tempvar, node in zip(exc_vars, self.excinfo_tuple.args):
4244 node.set_var(tempvar)
4245 self.excinfo_tuple.generate_evaluation_code(code)
4246 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4248 old_break_label, old_continue_label = code.break_label, code.continue_label
4249 code.break_label = code.new_label('except_break')
4250 code.continue_label = code.new_label('except_continue')
4252 old_exc_vars = code.funcstate.exc_vars
4253 code.funcstate.exc_vars = exc_vars
4254 self.body.generate_execution_code(code)
4255 code.funcstate.exc_vars = old_exc_vars
4256 for var in exc_vars:
4257 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4258 code.put_goto(end_label)
4260 if code.label_used(code.break_label):
4261 code.put_label(code.break_label)
4262 for var in exc_vars:
4263 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4264 code.put_goto(old_break_label)
4265 code.break_label = old_break_label
4267 if code.label_used(code.continue_label):
4268 code.put_label(code.continue_label)
4269 for var in exc_vars:
4270 code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
4271 code.put_goto(old_continue_label)
4272 code.continue_label = old_continue_label
4274 for temp in exc_vars:
4275 code.funcstate.release_temp(temp)
4277 code.putln(
4278 "}")
4280 def annotate(self, code):
4281 if self.pattern:
4282 self.pattern.annotate(code)
4283 if self.target:
4284 self.target.annotate(code)
4285 self.body.annotate(code)
4288 class TryFinallyStatNode(StatNode):
4289 # try ... finally statement
4290 #
4291 # body StatNode
4292 # finally_clause StatNode
4293 #
4294 # The plan is that we funnel all continue, break
4295 # return and error gotos into the beginning of the
4296 # finally block, setting a variable to remember which
4297 # one we're doing. At the end of the finally block, we
4298 # switch on the variable to figure out where to go.
4299 # In addition, if we're doing an error, we save the
4300 # exception on entry to the finally block and restore
4301 # it on exit.
4303 child_attrs = ["body", "finally_clause"]
4305 preserve_exception = 1
4307 disallow_continue_in_try_finally = 0
4308 # There doesn't seem to be any point in disallowing
4309 # continue in the try block, since we have no problem
4310 # handling it.
4312 def create_analysed(pos, env, body, finally_clause):
4313 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4314 return node
4315 create_analysed = staticmethod(create_analysed)
4317 def analyse_control_flow(self, env):
4318 env.start_branching(self.pos)
4319 self.body.analyse_control_flow(env)
4320 env.next_branch(self.body.end_pos())
4321 env.finish_branching(self.body.end_pos())
4322 self.finally_clause.analyse_control_flow(env)
4324 def analyse_declarations(self, env):
4325 self.body.analyse_declarations(env)
4326 self.finally_clause.analyse_declarations(env)
4328 def analyse_expressions(self, env):
4329 self.body.analyse_expressions(env)
4330 self.finally_clause.analyse_expressions(env)
4332 nogil_check = Node.gil_error
4333 gil_message = "Try-finally statement"
4335 def generate_execution_code(self, code):
4336 old_error_label = code.error_label
4337 old_labels = code.all_new_labels()
4338 new_labels = code.get_all_labels()
4339 new_error_label = code.error_label
4340 catch_label = code.new_label()
4341 code.putln(
4342 "/*try:*/ {")
4343 if self.disallow_continue_in_try_finally:
4344 was_in_try_finally = code.funcstate.in_try_finally
4345 code.funcstate.in_try_finally = 1
4346 self.body.generate_execution_code(code)
4347 if self.disallow_continue_in_try_finally:
4348 code.funcstate.in_try_finally = was_in_try_finally
4349 code.putln(
4350 "}")
4351 temps_to_clean_up = code.funcstate.all_free_managed_temps()
4352 code.putln(
4353 "/*finally:*/ {")
4354 cases_used = []
4355 error_label_used = 0
4356 for i, new_label in enumerate(new_labels):
4357 if new_label in code.labels_used:
4358 cases_used.append(i)
4359 if new_label == new_error_label:
4360 error_label_used = 1
4361 error_label_case = i
4362 if cases_used:
4363 code.putln(
4364 "int __pyx_why;")
4365 if error_label_used and self.preserve_exception:
4366 code.putln(
4367 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4368 code.putln(
4369 "int %s;" % Naming.exc_lineno_name)
4370 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4371 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4372 code.putln(exc_var_init_zero)
4373 else:
4374 exc_var_init_zero = None
4375 code.use_label(catch_label)
4376 code.putln(
4377 "__pyx_why = 0; goto %s;" % catch_label)
4378 for i in cases_used:
4379 new_label = new_labels[i]
4380 #if new_label and new_label != "<try>":
4381 if new_label == new_error_label and self.preserve_exception:
4382 self.put_error_catcher(code,
4383 new_error_label, i+1, catch_label, temps_to_clean_up)
4384 else:
4385 code.put('%s: ' % new_label)
4386 if exc_var_init_zero:
4387 code.putln(exc_var_init_zero)
4388 code.putln("__pyx_why = %s; goto %s;" % (
4389 i+1,
4390 catch_label))
4391 code.put_label(catch_label)
4392 code.set_all_labels(old_labels)
4393 if error_label_used:
4394 code.new_error_label()
4395 finally_error_label = code.error_label
4396 self.finally_clause.generate_execution_code(code)
4397 if error_label_used:
4398 if finally_error_label in code.labels_used and self.preserve_exception:
4399 over_label = code.new_label()
4400 code.put_goto(over_label);
4401 code.put_label(finally_error_label)
4402 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4403 for var in Naming.exc_vars:
4404 code.putln("Py_XDECREF(%s);" % var)
4405 code.putln("}")
4406 code.put_goto(old_error_label)
4407 code.put_label(over_label)
4408 code.error_label = old_error_label
4409 if cases_used:
4410 code.putln(
4411 "switch (__pyx_why) {")
4412 for i in cases_used:
4413 old_label = old_labels[i]
4414 if old_label == old_error_label and self.preserve_exception:
4415 self.put_error_uncatcher(code, i+1, old_error_label)
4416 else:
4417 code.use_label(old_label)
4418 code.putln(
4419 "case %s: goto %s;" % (
4420 i+1,
4421 old_label))
4422 code.putln(
4423 "}")
4424 code.putln(
4425 "}")
4427 def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
4428 code.globalstate.use_utility_code(restore_exception_utility_code)
4429 code.putln(
4430 "%s: {" %
4431 error_label)
4432 code.putln(
4433 "__pyx_why = %s;" %
4434 i)
4435 for temp_name, type in temps_to_clean_up:
4436 code.put_xdecref_clear(temp_name, type)
4437 code.putln(
4438 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4439 Naming.exc_vars)
4440 code.putln(
4441 "%s = %s;" % (
4442 Naming.exc_lineno_name, Naming.lineno_cname))
4443 #code.putln(
4444 # "goto %s;" %
4445 # catch_label)
4446 code.put_goto(catch_label)
4447 code.putln(
4448 "}")
4450 def put_error_uncatcher(self, code, i, error_label):
4451 code.globalstate.use_utility_code(restore_exception_utility_code)
4452 code.putln(
4453 "case %s: {" %
4454 i)
4455 code.putln(
4456 "__Pyx_ErrRestore(%s, %s, %s);" %
4457 Naming.exc_vars)
4458 code.putln(
4459 "%s = %s;" % (
4460 Naming.lineno_cname, Naming.exc_lineno_name))
4461 for var in Naming.exc_vars:
4462 code.putln(
4463 "%s = 0;" %
4464 var)
4465 code.put_goto(error_label)
4466 code.putln(
4467 "}")
4469 def annotate(self, code):
4470 self.body.annotate(code)
4471 self.finally_clause.annotate(code)
4474 class GILStatNode(TryFinallyStatNode):
4475 # 'with gil' or 'with nogil' statement
4476 #
4477 # state string 'gil' or 'nogil'
4479 # child_attrs = []
4481 preserve_exception = 0
4483 def __init__(self, pos, state, body):
4484 self.state = state
4485 TryFinallyStatNode.__init__(self, pos,
4486 body = body,
4487 finally_clause = GILExitNode(pos, state = state))
4489 def analyse_expressions(self, env):
4490 env.use_utility_code(force_init_threads_utility_code)
4491 was_nogil = env.nogil
4492 env.nogil = 1
4493 TryFinallyStatNode.analyse_expressions(self, env)
4494 env.nogil = was_nogil
4496 nogil_check = None
4498 def generate_execution_code(self, code):
4499 code.mark_pos(self.pos)
4500 if self.state == 'gil':
4501 code.putln("{ PyGILState_STATE _save = PyGILState_Ensure();")
4502 else:
4503 code.putln("{ PyThreadState *_save;")
4504 code.putln("Py_UNBLOCK_THREADS")
4505 TryFinallyStatNode.generate_execution_code(self, code)
4506 code.putln("}")
4509 class GILExitNode(StatNode):
4510 # Used as the 'finally' block in a GILStatNode
4511 #
4512 # state string 'gil' or 'nogil'
4514 child_attrs = []
4516 def analyse_expressions(self, env):
4517 pass
4519 def generate_execution_code(self, code):
4520 if self.state == 'gil':
4521 code.putln("PyGILState_Release();")
4522 else:
4523 code.putln("Py_BLOCK_THREADS")
4526 class CImportStatNode(StatNode):
4527 # cimport statement
4528 #
4529 # module_name string Qualified name of module being imported
4530 # as_name string or None Name specified in "as" clause, if any
4532 child_attrs = []
4534 def analyse_declarations(self, env):
4535 if not env.is_module_scope:
4536 error(self.pos, "cimport only allowed at module level")
4537 return
4538 module_scope = env.find_module(self.module_name, self.pos)
4539 if "." in self.module_name:
4540 names = [EncodedString(name) for name in self.module_name.split(".")]
4541 top_name = names[0]
4542 top_module_scope = env.context.find_submodule(top_name)
4543 module_scope = top_module_scope
4544 for name in names[1:]:
4545 submodule_scope = module_scope.find_submodule(name)
4546 module_scope.declare_module(name, submodule_scope, self.pos)
4547 module_scope = submodule_scope
4548 if self.as_name:
4549 env.declare_module(self.as_name, module_scope, self.pos)
4550 else:
4551 env.declare_module(top_name, top_module_scope, self.pos)
4552 else:
4553 name = self.as_name or self.module_name
4554 env.declare_module(name, module_scope, self.pos)
4556 def analyse_expressions(self, env):
4557 pass
4559 def generate_execution_code(self, code):
4560 pass
4563 class FromCImportStatNode(StatNode):
4564 # from ... cimport statement
4565 #
4566 # module_name string Qualified name of module
4567 # imported_names [(pos, name, as_name, kind)] Names to be imported
4569 child_attrs = []
4571 def analyse_declarations(self, env):
4572 if not env.is_module_scope:
4573 error(self.pos, "cimport only allowed at module level")
4574 return
4575 module_scope = env.find_module(self.module_name, self.pos)
4576 env.add_imported_module(module_scope)
4577 for pos, name, as_name, kind in self.imported_names:
4578 if name == "*":
4579 for local_name, entry in module_scope.entries.items():
4580 env.add_imported_entry(local_name, entry, pos)
4581 else:
4582 entry = module_scope.lookup(name)
4583 if entry:
4584 if kind and not self.declaration_matches(entry, kind):
4585 entry.redeclared(pos)
4586 else:
4587 if kind == 'struct' or kind == 'union':
4588 entry = module_scope.declare_struct_or_union(name,
4589 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4590 elif kind == 'class':
4591 entry = module_scope.declare_c_class(name, pos = pos,
4592 module_name = self.module_name)
4593 else:
4594 submodule_scope = env.context.find_module(name, relative_to = module_scope, pos = self.pos)
4595 if submodule_scope.parent_module is module_scope:
4596 env.declare_module(as_name or name, submodule_scope, self.pos)
4597 else:
4598 error(pos, "Name '%s' not declared in module '%s'"
4599 % (name, self.module_name))
4601 if entry:
4602 local_name = as_name or name
4603 env.add_imported_entry(local_name, entry, pos)
4605 def declaration_matches(self, entry, kind):
4606 if not entry.is_type:
4607 return 0
4608 type = entry.type
4609 if kind == 'class':
4610 if not type.is_extension_type:
4611 return 0
4612 else:
4613 if not type.is_struct_or_union:
4614 return 0
4615 if kind != type.kind:
4616 return 0
4617 return 1
4619 def analyse_expressions(self, env):
4620 pass
4622 def generate_execution_code(self, code):
4623 pass
4626 class FromImportStatNode(StatNode):
4627 # from ... import statement
4628 #
4629 # module ImportNode
4630 # items [(string, NameNode)]
4631 # interned_items [(string, NameNode, ExprNode)]
4632 # item PyTempNode used internally
4633 # import_star boolean used internally
4635 child_attrs = ["module"]
4636 import_star = 0
4638 def analyse_declarations(self, env):
4639 for name, target in self.items:
4640 if name == "*":
4641 if not env.is_module_scope:
4642 error(self.pos, "import * only allowed at module level")
4643 return
4644 env.has_import_star = 1
4645 self.import_star = 1
4646 else:
4647 target.analyse_target_declaration(env)
4649 def analyse_expressions(self, env):
4650 import ExprNodes
4651 self.module.analyse_expressions(env)
4652 self.item = ExprNodes.PyTempNode(self.pos, env)
4653 self.interned_items = []
4654 for name, target in self.items:
4655 if name == '*':
4656 for _, entry in env.entries.items():
4657 if not entry.is_type and entry.type.is_extension_type:
4658 env.use_utility_code(ExprNodes.type_test_utility_code)
4659 break
4660 else:
4661 entry = env.lookup(target.name)
4662 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4663 continue # already cimported
4664 target.analyse_target_expression(env, None)
4665 if target.type is py_object_type:
4666 coerced_item = None
4667 else:
4668 coerced_item = self.item.coerce_to(target.type, env)
4669 self.interned_items.append(
4670 (name, target, coerced_item))
4672 def generate_execution_code(self, code):
4673 self.module.generate_evaluation_code(code)
4674 if self.import_star:
4675 code.putln(
4676 'if (%s(%s) < 0) %s;' % (
4677 Naming.import_star,
4678 self.module.py_result(),
4679 code.error_goto(self.pos)))
4680 self.item.allocate(code)
4681 for name, target, coerced_item in self.interned_items:
4682 cname = code.intern_identifier(name)
4683 code.putln(
4684 '%s = PyObject_GetAttr(%s, %s); %s' % (
4685 self.item.result(),
4686 self.module.py_result(),
4687 cname,
4688 code.error_goto_if_null(self.item.result(), self.pos)))
4689 code.put_gotref(self.item.py_result())
4690 if coerced_item is None:
4691 target.generate_assignment_code(self.item, code)
4692 else:
4693 coerced_item.allocate_temp_result(code)
4694 coerced_item.generate_result_code(code)
4695 target.generate_assignment_code(coerced_item, code)
4696 if self.item.result() != coerced_item.result():
4697 code.put_decref_clear(self.item.result(), self.item.type)
4698 self.item.release(code)
4699 self.module.generate_disposal_code(code)
4700 self.module.free_temps(code)
4704 #------------------------------------------------------------------------------------
4705 #
4706 # Runtime support code
4707 #
4708 #------------------------------------------------------------------------------------
4710 utility_function_predeclarations = \
4711 """
4712 #ifdef __GNUC__
4713 #define INLINE __inline__
4714 #elif _WIN32
4715 #define INLINE __inline
4716 #else
4717 #define INLINE
4718 #endif
4720 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4722 """ + """
4724 static int %(skip_dispatch_cname)s = 0;
4726 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4728 if Options.gcc_branch_hints:
4729 branch_prediction_macros = \
4730 """
4731 #ifdef __GNUC__
4732 /* Test for GCC > 2.95 */
4733 #if __GNUC__ > 2 || \
4734 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4735 #define likely(x) __builtin_expect(!!(x), 1)
4736 #define unlikely(x) __builtin_expect(!!(x), 0)
4737 #else /* __GNUC__ > 2 ... */
4738 #define likely(x) (x)
4739 #define unlikely(x) (x)
4740 #endif /* __GNUC__ > 2 ... */
4741 #else /* __GNUC__ */
4742 #define likely(x) (x)
4743 #define unlikely(x) (x)
4744 #endif /* __GNUC__ */
4745 """
4746 else:
4747 branch_prediction_macros = \
4748 """
4749 #define likely(x) (x)
4750 #define unlikely(x) (x)
4751 """
4753 #get_name_predeclaration = \
4754 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4756 #get_name_interned_predeclaration = \
4757 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4759 #------------------------------------------------------------------------------------
4761 printing_utility_code = UtilityCode(
4762 proto = """
4763 static int __Pyx_Print(PyObject *, int); /*proto*/
4764 #if PY_MAJOR_VERSION >= 3
4765 static PyObject* %s = 0;
4766 static PyObject* %s = 0;
4767 #endif
4768 """ % (Naming.print_function, Naming.print_function_kwargs),
4769 impl = r"""
4770 #if PY_MAJOR_VERSION < 3
4771 static PyObject *__Pyx_GetStdout(void) {
4772 PyObject *f = PySys_GetObject((char *)"stdout");
4773 if (!f) {
4774 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4775 }
4776 return f;
4777 }
4779 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4780 PyObject *f;
4781 PyObject* v;
4782 int i;
4784 if (!(f = __Pyx_GetStdout()))
4785 return -1;
4786 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4787 if (PyFile_SoftSpace(f, 1)) {
4788 if (PyFile_WriteString(" ", f) < 0)
4789 return -1;
4790 }
4791 v = PyTuple_GET_ITEM(arg_tuple, i);
4792 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4793 return -1;
4794 if (PyString_Check(v)) {
4795 char *s = PyString_AsString(v);
4796 Py_ssize_t len = PyString_Size(v);
4797 if (len > 0 &&
4798 isspace(Py_CHARMASK(s[len-1])) &&
4799 s[len-1] != ' ')
4800 PyFile_SoftSpace(f, 0);
4801 }
4802 }
4803 if (newline) {
4804 if (PyFile_WriteString("\n", f) < 0)
4805 return -1;
4806 PyFile_SoftSpace(f, 0);
4807 }
4808 return 0;
4809 }
4811 #else /* Python 3 has a print function */
4813 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4814 PyObject* kwargs = 0;
4815 PyObject* result = 0;
4816 PyObject* end_string;
4817 if (!%(PRINT_FUNCTION)s) {
4818 %(PRINT_FUNCTION)s = __Pyx_GetAttrString(%(BUILTINS)s, "print");
4819 if (!%(PRINT_FUNCTION)s)
4820 return -1;
4821 }
4822 if (!newline) {
4823 if (!%(PRINT_KWARGS)s) {
4824 %(PRINT_KWARGS)s = PyDict_New();
4825 if (!%(PRINT_KWARGS)s)
4826 return -1;
4827 end_string = PyUnicode_FromStringAndSize(" ", 1);
4828 if (!end_string)
4829 return -1;
4830 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4831 Py_DECREF(end_string);
4832 return -1;
4833 }
4834 Py_DECREF(end_string);
4835 }
4836 kwargs = %(PRINT_KWARGS)s;
4837 }
4838 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4839 if (!result)
4840 return -1;
4841 Py_DECREF(result);
4842 return 0;
4843 }
4845 #endif
4846 """ % {'BUILTINS' : Naming.builtins_cname,
4847 'PRINT_FUNCTION' : Naming.print_function,
4848 'PRINT_KWARGS' : Naming.print_function_kwargs}
4849 )
4852 printing_one_utility_code = UtilityCode(
4853 proto = """
4854 static int __Pyx_PrintOne(PyObject *o); /*proto*/
4855 """,
4856 impl = r"""
4857 #if PY_MAJOR_VERSION < 3
4859 static int __Pyx_PrintOne(PyObject *o) {
4860 PyObject *f;
4861 if (!(f = __Pyx_GetStdout()))
4862 return -1;
4863 if (PyFile_SoftSpace(f, 0)) {
4864 if (PyFile_WriteString(" ", f) < 0)
4865 return -1;
4866 }
4867 if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0)
4868 return -1;
4869 if (PyFile_WriteString("\n", f) < 0)
4870 return -1;
4871 return 0;
4872 /* the line below is just to avoid compiler
4873 * compiler warnings about unused functions */
4874 return __Pyx_Print(NULL, 0);
4875 }
4877 #else /* Python 3 has a print function */
4879 static int __Pyx_PrintOne(PyObject *o) {
4880 int res;
4881 PyObject* arg_tuple = PyTuple_New(1);
4882 if (unlikely(!arg_tuple))
4883 return -1;
4884 Py_INCREF(o);
4885 PyTuple_SET_ITEM(arg_tuple, 0, o);
4886 res = __Pyx_Print(arg_tuple, 1);
4887 Py_DECREF(arg_tuple);
4888 return res;
4889 }
4891 #endif
4892 """,
4893 requires=[printing_utility_code])
4897 #------------------------------------------------------------------------------------
4899 # The following function is based on do_raise() from ceval.c.
4901 raise_utility_code = UtilityCode(
4902 proto = """
4903 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4904 """,
4905 impl = """
4906 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4907 Py_XINCREF(type);
4908 Py_XINCREF(value);
4909 Py_XINCREF(tb);
4910 /* First, check the traceback argument, replacing None with NULL. */
4911 if (tb == Py_None) {
4912 Py_DECREF(tb);
4913 tb = 0;
4914 }
4915 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4916 PyErr_SetString(PyExc_TypeError,
4917 "raise: arg 3 must be a traceback or None");
4918 goto raise_error;
4919 }
4920 /* Next, replace a missing value with None */
4921 if (value == NULL) {
4922 value = Py_None;
4923 Py_INCREF(value);
4924 }
4925 #if PY_VERSION_HEX < 0x02050000
4926 if (!PyClass_Check(type))
4927 #else
4928 if (!PyType_Check(type))
4929 #endif
4930 {
4931 /* Raising an instance. The value should be a dummy. */
4932 if (value != Py_None) {
4933 PyErr_SetString(PyExc_TypeError,
4934 "instance exception may not have a separate value");
4935 goto raise_error;
4936 }
4937 /* Normalize to raise <class>, <instance> */
4938 Py_DECREF(value);
4939 value = type;
4940 #if PY_VERSION_HEX < 0x02050000
4941 if (PyInstance_Check(type)) {
4942 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4943 Py_INCREF(type);
4944 }
4945 else {
4946 type = 0;
4947 PyErr_SetString(PyExc_TypeError,
4948 "raise: exception must be an old-style class or instance");
4949 goto raise_error;
4950 }
4951 #else
4952 type = (PyObject*) Py_TYPE(type);
4953 Py_INCREF(type);
4954 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4955 PyErr_SetString(PyExc_TypeError,
4956 "raise: exception class must be a subclass of BaseException");
4957 goto raise_error;
4958 }
4959 #endif
4960 }
4961 __Pyx_ErrRestore(type, value, tb);
4962 return;
4963 raise_error:
4964 Py_XDECREF(value);
4965 Py_XDECREF(type);
4966 Py_XDECREF(tb);
4967 return;
4968 }
4969 """)
4971 #------------------------------------------------------------------------------------
4973 reraise_utility_code = UtilityCode(
4974 proto = """
4975 static void __Pyx_ReRaise(void); /*proto*/
4976 """,
4977 impl = """
4978 static void __Pyx_ReRaise(void) {
4979 PyThreadState *tstate = PyThreadState_GET();
4980 PyObject* tmp_type = tstate->curexc_type;
4981 PyObject* tmp_value = tstate->curexc_value;
4982 PyObject* tmp_tb = tstate->curexc_traceback;
4983 tstate->curexc_type = tstate->exc_type;
4984 tstate->curexc_value = tstate->exc_value;
4985 tstate->curexc_traceback = tstate->exc_traceback;
4986 tstate->exc_type = 0;
4987 tstate->exc_value = 0;
4988 tstate->exc_traceback = 0;
4989 Py_XDECREF(tmp_type);
4990 Py_XDECREF(tmp_value);
4991 Py_XDECREF(tmp_tb);
4992 }
4993 """)
4995 #------------------------------------------------------------------------------------
4997 arg_type_test_utility_code = UtilityCode(
4998 proto = """
4999 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5000 const char *name, int exact); /*proto*/
5001 """,
5002 impl = """
5003 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
5004 const char *name, int exact)
5005 {
5006 if (!type) {
5007 PyErr_Format(PyExc_SystemError, "Missing type object");
5008 return 0;
5009 }
5010 if (none_allowed && obj == Py_None) return 1;
5011 else if (exact) {
5012 if (Py_TYPE(obj) == type) return 1;
5013 }
5014 else {
5015 if (PyObject_TypeCheck(obj, type)) return 1;
5016 }
5017 PyErr_Format(PyExc_TypeError,
5018 "Argument '%s' has incorrect type (expected %s, got %s)",
5019 name, type->tp_name, Py_TYPE(obj)->tp_name);
5020 return 0;
5021 }
5022 """)
5024 #------------------------------------------------------------------------------------
5025 #
5026 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
5027 # many or too few positional arguments were found. This handles
5028 # Py_ssize_t formatting correctly.
5030 raise_argtuple_invalid_utility_code = UtilityCode(
5031 proto = """
5032 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
5033 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
5034 """,
5035 impl = """
5036 static void __Pyx_RaiseArgtupleInvalid(
5037 const char* func_name,
5038 int exact,
5039 Py_ssize_t num_min,
5040 Py_ssize_t num_max,
5041 Py_ssize_t num_found)
5042 {
5043 Py_ssize_t num_expected;
5044 const char *number, *more_or_less;
5046 if (num_found < num_min) {
5047 num_expected = num_min;
5048 more_or_less = "at least";
5049 } else {
5050 num_expected = num_max;
5051 more_or_less = "at most";
5052 }
5053 if (exact) {
5054 more_or_less = "exactly";
5055 }
5056 number = (num_expected == 1) ? "" : "s";
5057 PyErr_Format(PyExc_TypeError,
5058 #if PY_VERSION_HEX < 0x02050000
5059 "%s() takes %s %d positional argument%s (%d given)",
5060 #else
5061 "%s() takes %s %zd positional argument%s (%zd given)",
5062 #endif
5063 func_name, more_or_less, num_expected, number, num_found);
5064 }
5065 """)
5067 raise_keyword_required_utility_code = UtilityCode(
5068 proto = """
5069 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
5070 """,
5071 impl = """
5072 static INLINE void __Pyx_RaiseKeywordRequired(
5073 const char* func_name,
5074 PyObject* kw_name)
5075 {
5076 PyErr_Format(PyExc_TypeError,
5077 #if PY_MAJOR_VERSION >= 3
5078 "%s() needs keyword-only argument %U", func_name, kw_name);
5079 #else
5080 "%s() needs keyword-only argument %s", func_name,
5081 PyString_AS_STRING(kw_name));
5082 #endif
5083 }
5084 """)
5086 raise_double_keywords_utility_code = UtilityCode(
5087 proto = """
5088 static void __Pyx_RaiseDoubleKeywordsError(
5089 const char* func_name, PyObject* kw_name); /*proto*/
5090 """,
5091 impl = """
5092 static void __Pyx_RaiseDoubleKeywordsError(
5093 const char* func_name,
5094 PyObject* kw_name)
5095 {
5096 PyErr_Format(PyExc_TypeError,
5097 #if PY_MAJOR_VERSION >= 3
5098 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
5099 #else
5100 "%s() got multiple values for keyword argument '%s'", func_name,
5101 PyString_AS_STRING(kw_name));
5102 #endif
5103 }
5104 """)
5106 #------------------------------------------------------------------------------------
5107 #
5108 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
5109 # were passed to a function, or if any keywords were passed to a
5110 # function that does not accept them.
5112 keyword_string_check_utility_code = UtilityCode(
5113 proto = """
5114 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
5115 const char* function_name, int kw_allowed); /*proto*/
5116 """,
5117 impl = """
5118 static INLINE int __Pyx_CheckKeywordStrings(
5119 PyObject *kwdict,
5120 const char* function_name,
5121 int kw_allowed)
5122 {
5123 PyObject* key = 0;
5124 Py_ssize_t pos = 0;
5125 while (PyDict_Next(kwdict, &pos, &key, 0)) {
5126 #if PY_MAJOR_VERSION < 3
5127 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
5128 #else
5129 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
5130 #endif
5131 goto invalid_keyword_type;
5132 }
5133 if ((!kw_allowed) && unlikely(key))
5134 goto invalid_keyword;
5135 return 1;
5136 invalid_keyword_type:
5137 PyErr_Format(PyExc_TypeError,
5138 "%s() keywords must be strings", function_name);
5139 return 0;
5140 invalid_keyword:
5141 PyErr_Format(PyExc_TypeError,
5142 #if PY_MAJOR_VERSION < 3
5143 "%s() got an unexpected keyword argument '%s'",
5144 function_name, PyString_AsString(key));
5145 #else
5146 "%s() got an unexpected keyword argument '%U'",
5147 function_name, key);
5148 #endif
5149 return 0;
5150 }
5151 """)
5153 #------------------------------------------------------------------------------------
5154 #
5155 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
5156 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
5157 # keywords will raise an invalid keyword error.
5158 #
5159 # Three kinds of errors are checked: 1) non-string keywords, 2)
5160 # unexpected keywords and 3) overlap with positional arguments.
5161 #
5162 # If num_posargs is greater 0, it denotes the number of positional
5163 # arguments that were passed and that must therefore not appear
5164 # amongst the keywords as well.
5165 #
5166 # This method does not check for required keyword arguments.
5167 #
5169 parse_keywords_utility_code = UtilityCode(
5170 proto = """
5171 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
5172 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
5173 const char* function_name); /*proto*/
5174 """,
5175 impl = """
5176 static int __Pyx_ParseOptionalKeywords(
5177 PyObject *kwds,
5178 PyObject **argnames[],
5179 PyObject *kwds2,
5180 PyObject *values[],
5181 Py_ssize_t num_pos_args,
5182 const char* function_name)
5183 {
5184 PyObject *key = 0, *value = 0;
5185 Py_ssize_t pos = 0;
5186 PyObject*** name;
5187 PyObject*** first_kw_arg = argnames + num_pos_args;
5189 while (PyDict_Next(kwds, &pos, &key, &value)) {
5190 name = first_kw_arg;
5191 while (*name && (**name != key)) name++;
5192 if (*name) {
5193 values[name-argnames] = value;
5194 } else {
5195 #if PY_MAJOR_VERSION < 3
5196 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
5197 #else
5198 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
5199 #endif
5200 goto invalid_keyword_type;
5201 } else {
5202 for (name = first_kw_arg; *name; name++) {
5203 #if PY_MAJOR_VERSION >= 3
5204 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5205 PyUnicode_Compare(**name, key) == 0) break;
5206 #else
5207 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5208 _PyString_Eq(**name, key)) break;
5209 #endif
5210 }
5211 if (*name) {
5212 values[name-argnames] = value;
5213 } else {
5214 /* unexpected keyword found */
5215 for (name=argnames; name != first_kw_arg; name++) {
5216 if (**name == key) goto arg_passed_twice;
5217 #if PY_MAJOR_VERSION >= 3
5218 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5219 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5220 #else
5221 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5222 _PyString_Eq(**name, key)) goto arg_passed_twice;
5223 #endif
5224 }
5225 if (kwds2) {
5226 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5227 } else {
5228 goto invalid_keyword;
5229 }
5230 }
5231 }
5232 }
5233 }
5234 return 0;
5235 arg_passed_twice:
5236 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5237 goto bad;
5238 invalid_keyword_type:
5239 PyErr_Format(PyExc_TypeError,
5240 "%s() keywords must be strings", function_name);
5241 goto bad;
5242 invalid_keyword:
5243 PyErr_Format(PyExc_TypeError,
5244 #if PY_MAJOR_VERSION < 3
5245 "%s() got an unexpected keyword argument '%s'",
5246 function_name, PyString_AsString(key));
5247 #else
5248 "%s() got an unexpected keyword argument '%U'",
5249 function_name, key);
5250 #endif
5251 bad:
5252 return -1;
5253 }
5254 """)
5256 #------------------------------------------------------------------------------------
5258 traceback_utility_code = UtilityCode(
5259 proto = """
5260 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5261 """,
5262 impl = """
5263 #include "compile.h"
5264 #include "frameobject.h"
5265 #include "traceback.h"
5267 static void __Pyx_AddTraceback(const char *funcname) {
5268 PyObject *py_srcfile = 0;
5269 PyObject *py_funcname = 0;
5270 PyObject *py_globals = 0;
5271 PyObject *empty_string = 0;
5272 PyCodeObject *py_code = 0;
5273 PyFrameObject *py_frame = 0;
5275 #if PY_MAJOR_VERSION < 3
5276 py_srcfile = PyString_FromString(%(FILENAME)s);
5277 #else
5278 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5279 #endif
5280 if (!py_srcfile) goto bad;
5281 if (%(CLINENO)s) {
5282 #if PY_MAJOR_VERSION < 3
5283 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5284 #else
5285 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5286 #endif
5287 }
5288 else {
5289 #if PY_MAJOR_VERSION < 3
5290 py_funcname = PyString_FromString(funcname);
5291 #else
5292 py_funcname = PyUnicode_FromString(funcname);
5293 #endif
5294 }
5295 if (!py_funcname) goto bad;
5296 py_globals = PyModule_GetDict(%(GLOBALS)s);
5297 if (!py_globals) goto bad;
5298 #if PY_MAJOR_VERSION < 3
5299 empty_string = PyString_FromStringAndSize("", 0);
5300 #else
5301 empty_string = PyBytes_FromStringAndSize("", 0);
5302 #endif
5303 if (!empty_string) goto bad;
5304 py_code = PyCode_New(
5305 0, /*int argcount,*/
5306 #if PY_MAJOR_VERSION >= 3
5307 0, /*int kwonlyargcount,*/
5308 #endif
5309 0, /*int nlocals,*/
5310 0, /*int stacksize,*/
5311 0, /*int flags,*/
5312 empty_string, /*PyObject *code,*/
5313 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5314 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5315 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5316 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5317 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5318 py_srcfile, /*PyObject *filename,*/
5319 py_funcname, /*PyObject *name,*/
5320 %(LINENO)s, /*int firstlineno,*/
5321 empty_string /*PyObject *lnotab*/
5322 );
5323 if (!py_code) goto bad;
5324 py_frame = PyFrame_New(
5325 PyThreadState_GET(), /*PyThreadState *tstate,*/
5326 py_code, /*PyCodeObject *code,*/
5327 py_globals, /*PyObject *globals,*/
5328 0 /*PyObject *locals*/
5329 );
5330 if (!py_frame) goto bad;
5331 py_frame->f_lineno = %(LINENO)s;
5332 PyTraceBack_Here(py_frame);
5333 bad:
5334 Py_XDECREF(py_srcfile);
5335 Py_XDECREF(py_funcname);
5336 Py_XDECREF(empty_string);
5337 Py_XDECREF(py_code);
5338 Py_XDECREF(py_frame);
5339 }
5340 """ % {
5341 'FILENAME': Naming.filename_cname,
5342 'LINENO': Naming.lineno_cname,
5343 'CFILENAME': Naming.cfilenm_cname,
5344 'CLINENO': Naming.clineno_cname,
5345 'GLOBALS': Naming.module_cname,
5346 'EMPTY_TUPLE' : Naming.empty_tuple,
5347 })
5349 restore_exception_utility_code = UtilityCode(
5350 proto = """
5351 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5352 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5353 """,
5354 impl = """
5355 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5356 PyObject *tmp_type, *tmp_value, *tmp_tb;
5357 PyThreadState *tstate = PyThreadState_GET();
5359 #if PY_MAJOR_VERSION >= 3
5360 /* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
5361 if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
5362 tmp_type = tstate->exc_type;
5363 tmp_value = tstate->exc_value;
5364 tmp_tb = tstate->exc_traceback;
5365 PyErr_NormalizeException(&type, &value, &tb);
5366 PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
5367 tstate->exc_type = 0;
5368 tstate->exc_value = 0;
5369 tstate->exc_traceback = 0;
5370 PyException_SetContext(value, tmp_value);
5371 Py_DECREF(tmp_type);
5372 Py_XDECREF(tmp_tb);
5373 }
5374 #endif
5376 tmp_type = tstate->curexc_type;
5377 tmp_value = tstate->curexc_value;
5378 tmp_tb = tstate->curexc_traceback;
5379 tstate->curexc_type = type;
5380 tstate->curexc_value = value;
5381 tstate->curexc_traceback = tb;
5382 Py_XDECREF(tmp_type);
5383 Py_XDECREF(tmp_value);
5384 Py_XDECREF(tmp_tb);
5385 }
5387 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5388 PyThreadState *tstate = PyThreadState_GET();
5389 *type = tstate->curexc_type;
5390 *value = tstate->curexc_value;
5391 *tb = tstate->curexc_traceback;
5393 tstate->curexc_type = 0;
5394 tstate->curexc_value = 0;
5395 tstate->curexc_traceback = 0;
5396 }
5398 """)
5400 #------------------------------------------------------------------------------------
5402 unraisable_exception_utility_code = UtilityCode(
5403 proto = """
5404 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5405 """,
5406 impl = """
5407 static void __Pyx_WriteUnraisable(const char *name) {
5408 PyObject *old_exc, *old_val, *old_tb;
5409 PyObject *ctx;
5410 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5411 #if PY_MAJOR_VERSION < 3
5412 ctx = PyString_FromString(name);
5413 #else
5414 ctx = PyUnicode_FromString(name);
5415 #endif
5416 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5417 if (!ctx) {
5418 PyErr_WriteUnraisable(Py_None);
5419 } else {
5420 PyErr_WriteUnraisable(ctx);
5421 Py_DECREF(ctx);
5422 }
5423 }
5424 """,
5425 requires=[restore_exception_utility_code])
5427 #------------------------------------------------------------------------------------
5429 set_vtable_utility_code = UtilityCode(
5430 proto = """
5431 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5432 """,
5433 impl = """
5434 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5435 PyObject *pycobj = 0;
5436 int result;
5438 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5439 if (!pycobj)
5440 goto bad;
5441 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5442 goto bad;
5443 result = 0;
5444 goto done;
5446 bad:
5447 result = -1;
5448 done:
5449 Py_XDECREF(pycobj);
5450 return result;
5451 }
5452 """)
5454 #------------------------------------------------------------------------------------
5456 get_vtable_utility_code = UtilityCode(
5457 proto = """
5458 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5459 """,
5460 impl = r"""
5461 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5462 int result;
5463 PyObject *pycobj;
5465 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5466 if (!pycobj)
5467 goto bad;
5468 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5469 if (!*(void **)vtabptr)
5470 goto bad;
5471 result = 0;
5472 goto done;
5474 bad:
5475 result = -1;
5476 done:
5477 Py_XDECREF(pycobj);
5478 return result;
5479 }
5480 """)
5482 #------------------------------------------------------------------------------------
5484 init_string_tab_utility_code = UtilityCode(
5485 proto = """
5486 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5487 """,
5488 impl = """
5489 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5490 while (t->p) {
5491 #if PY_MAJOR_VERSION < 3
5492 if (t->is_unicode && (!t->is_identifier)) {
5493 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5494 } else if (t->intern) {
5495 *t->p = PyString_InternFromString(t->s);
5496 } else {
5497 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5498 }
5499 #else /* Python 3+ has unicode identifiers */
5500 if (t->is_identifier || (t->is_unicode && t->intern)) {
5501 *t->p = PyUnicode_InternFromString(t->s);
5502 } else if (t->is_unicode) {
5503 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5504 } else {
5505 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5506 }
5507 #endif
5508 if (!*t->p)
5509 return -1;
5510 ++t;
5511 }
5512 return 0;
5513 }
5514 """)
5516 #------------------------------------------------------------------------------------
5518 get_exception_utility_code = UtilityCode(
5519 proto = """
5520 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5521 """,
5522 impl = """
5523 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5524 PyObject *tmp_type, *tmp_value, *tmp_tb;
5525 PyThreadState *tstate = PyThreadState_GET();
5526 *type = tstate->curexc_type;
5527 *value = tstate->curexc_value;
5528 *tb = tstate->curexc_traceback;
5529 tstate->curexc_type = 0;
5530 tstate->curexc_value = 0;
5531 tstate->curexc_traceback = 0;
5532 PyErr_NormalizeException(type, value, tb);
5533 if (PyErr_Occurred())
5534 goto bad;
5535 Py_INCREF(*type);
5536 Py_INCREF(*value);
5537 Py_INCREF(*tb);
5538 tmp_type = tstate->exc_type;
5539 tmp_value = tstate->exc_value;
5540 tmp_tb = tstate->exc_traceback;
5541 tstate->exc_type = *type;
5542 tstate->exc_value = *value;
5543 tstate->exc_traceback = *tb;
5544 /* Make sure tstate is in a consistent state when we XDECREF
5545 these objects (XDECREF may run arbitrary code). */
5546 Py_XDECREF(tmp_type);
5547 Py_XDECREF(tmp_value);
5548 Py_XDECREF(tmp_tb);
5549 return 0;
5550 bad:
5551 Py_XDECREF(*type);
5552 Py_XDECREF(*value);
5553 Py_XDECREF(*tb);
5554 return -1;
5555 }
5557 """)
5559 #------------------------------------------------------------------------------------
5561 reset_exception_utility_code = UtilityCode(
5562 proto = """
5563 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5564 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5565 """,
5566 impl = """
5567 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5568 PyThreadState *tstate = PyThreadState_GET();
5569 *type = tstate->exc_type;
5570 *value = tstate->exc_value;
5571 *tb = tstate->exc_traceback;
5572 Py_XINCREF(*type);
5573 Py_XINCREF(*value);
5574 Py_XINCREF(*tb);
5575 }
5577 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5578 PyObject *tmp_type, *tmp_value, *tmp_tb;
5579 PyThreadState *tstate = PyThreadState_GET();
5580 tmp_type = tstate->exc_type;
5581 tmp_value = tstate->exc_value;
5582 tmp_tb = tstate->exc_traceback;
5583 tstate->exc_type = type;
5584 tstate->exc_value = value;
5585 tstate->exc_traceback = tb;
5586 Py_XDECREF(tmp_type);
5587 Py_XDECREF(tmp_value);
5588 Py_XDECREF(tmp_tb);
5589 }
5590 """)
5592 #------------------------------------------------------------------------------------
5594 force_init_threads_utility_code = UtilityCode(
5595 proto="""
5596 #ifndef __PYX_FORCE_INIT_THREADS
5597 #if PY_VERSION_HEX < 0x02040200
5598 #define __PYX_FORCE_INIT_THREADS 1
5599 #else
5600 #define __PYX_FORCE_INIT_THREADS 0
5601 #endif
5602 #endif
5603 """)
5605 #------------------------------------------------------------------------------------
