Cython has moved to github.
cython-devel
view Cython/Compiler/Nodes.py @ 1409:151d8366f329
Inline function definitions in pxd files
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Thu Nov 27 19:29:12 2008 +0100 (3 years ago) |
| parents | 34f7903f26d0 |
| children | 15459e336874 |
line source
1 #
2 # Pyrex - Parse tree nodes
3 #
5 import string, 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, UtilityCode
17 from StringEncoding import EncodedString, escape_byte_string, split_docstring
18 import Options
19 import ControlFlow
21 from DebugFlags import debug_disposal_code
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
71 class Node(object):
72 # pos (string, int, int) Source file position
73 # is_name boolean Is a NameNode
74 # is_literal boolean Is a ConstNode
76 is_name = 0
77 is_literal = 0
78 temps = None
80 # All descandants should set child_attrs to a list of the attributes
81 # containing nodes considered "children" in the tree. Each such attribute
82 # can either contain a single node or a list of nodes. See Visitor.py.
83 child_attrs = None
85 def __init__(self, pos, **kw):
86 self.pos = pos
87 self.__dict__.update(kw)
89 gil_message = "Operation"
91 def gil_check(self, env):
92 if env.nogil:
93 self.gil_error()
95 def gil_error(self):
96 error(self.pos, "%s not allowed without gil" % self.gil_message)
98 def clone_node(self):
99 """Clone the node. This is defined as a shallow copy, except for member lists
100 amongst the child attributes (from get_child_accessors) which are also
101 copied. Lists containing child nodes are thus seen as a way for the node
102 to hold multiple children directly; the list is not treated as a seperate
103 level in the tree."""
104 result = copy.copy(self)
105 for attrname in result.child_attrs:
106 value = getattr(result, attrname)
107 if isinstance(value, list):
108 setattr(result, attrname, [x for x in value])
109 return result
112 #
113 # There are 4 phases of parse tree processing, applied in order to
114 # all the statements in a given scope-block:
115 #
116 # (0) analyse_control_flow
117 # Create the control flow tree into which state can be asserted and
118 # queried.
119 #
120 # (1) analyse_declarations
121 # Make symbol table entries for all declarations at the current
122 # level, both explicit (def, cdef, etc.) and implicit (assignment
123 # to an otherwise undeclared name).
124 #
125 # (2) analyse_expressions
126 # Determine the result types of expressions and fill in the
127 # 'type' attribute of each ExprNode. Insert coercion nodes into the
128 # tree where needed to convert to and from Python objects.
129 # Allocate temporary locals for intermediate results. Fill
130 # in the 'result_code' attribute of each ExprNode with a C code
131 # fragment.
132 #
133 # (3) generate_code
134 # Emit C code for all declarations, statements and expressions.
135 # Recursively applies the 3 processing phases to the bodies of
136 # functions.
137 #
139 def analyse_control_flow(self, env):
140 pass
142 def analyse_declarations(self, env):
143 pass
145 def analyse_expressions(self, env):
146 raise InternalError("analyse_expressions not implemented for %s" % \
147 self.__class__.__name__)
149 def generate_code(self, code):
150 raise InternalError("generate_code not implemented for %s" % \
151 self.__class__.__name__)
153 def annotate(self, code):
154 # mro does the wrong thing
155 if isinstance(self, BlockNode):
156 self.body.annotate(code)
158 def end_pos(self):
159 if not self.child_attrs:
160 return self.pos
161 try:
162 return self._end_pos
163 except AttributeError:
164 pos = self.pos
165 for attr in self.child_attrs:
166 child = getattr(self, attr)
167 # Sometimes lists, sometimes nodes
168 if child is None:
169 pass
170 elif isinstance(child, list):
171 for c in child:
172 pos = max(pos, c.end_pos())
173 else:
174 pos = max(pos, child.end_pos())
175 self._end_pos = pos
176 return pos
178 def dump(self, level=0, filter_out=("pos",), cutoff=100, encountered=None):
179 if cutoff == 0:
180 return "<...nesting level cutoff...>"
181 if encountered is None:
182 encountered = set()
183 if id(self) in encountered:
184 return "<%s (%d) -- already output>" % (self.__class__.__name__, id(self))
185 encountered.add(id(self))
187 def dump_child(x, level):
188 if isinstance(x, Node):
189 return x.dump(level, filter_out, cutoff-1, encountered)
190 elif isinstance(x, list):
191 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
192 else:
193 return repr(x)
196 attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
197 if len(attrs) == 0:
198 return "<%s (%d)>" % (self.__class__.__name__, id(self))
199 else:
200 indent = " " * level
201 res = "<%s (%d)\n" % (self.__class__.__name__, id(self))
202 for key, value in attrs:
203 res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
204 res += "%s>" % indent
205 return res
207 class CompilerDirectivesNode(Node):
208 """
209 Sets compiler directives for the children nodes
210 """
211 # directives {string:value} A dictionary holding the right value for
212 # *all* possible directives.
213 # body Node
214 child_attrs = ["body"]
216 def analyse_control_flow(self, env):
217 old = env.directives
218 env.directives = self.directives
219 self.body.analyse_control_flow(env)
220 env.directives = old
222 def analyse_declarations(self, env):
223 old = env.directives
224 env.directives = self.directives
225 self.body.analyse_declarations(env)
226 env.directives = old
228 def analyse_expressions(self, env):
229 old = env.directives
230 env.directives = self.directives
231 self.body.analyse_expressions(env)
232 env.directives = old
234 def generate_function_definitions(self, env, code):
235 env_old = env.directives
236 code_old = code.globalstate.directives
237 code.globalstate.directives = self.directives
238 self.body.generate_function_definitions(env, code)
239 env.directives = env_old
240 code.globalstate.directives = code_old
242 def generate_execution_code(self, code):
243 old = code.globalstate.directives
244 code.globalstate.directives = self.directives
245 self.body.generate_execution_code(code)
246 code.globalstate.directives = old
248 def annotate(self, code):
249 old = code.globalstate.directives
250 code.globalstate.directives = self.directives
251 self.body.annotate(code)
252 code.globalstate.directives = old
254 class BlockNode:
255 # Mixin class for nodes representing a declaration block.
257 def generate_const_definitions(self, env, code):
258 if env.const_entries:
259 for entry in env.const_entries:
260 if not entry.is_interned:
261 code.globalstate.add_const_definition(entry)
263 def generate_interned_string_decls(self, env, code):
264 entries = env.global_scope().new_interned_string_entries
265 if entries:
266 for entry in entries:
267 code.globalstate.add_interned_string_decl(entry)
268 del entries[:]
270 def generate_py_string_decls(self, env, code):
271 if env is None:
272 return # earlier error
273 entries = env.pystring_entries
274 if entries:
275 for entry in entries:
276 if not entry.is_interned:
277 code.globalstate.add_py_string_decl(entry)
279 def generate_interned_num_decls(self, env, code):
280 # Flush accumulated interned nums from the global scope
281 # and generate declarations for them.
282 genv = env.global_scope()
283 entries = genv.interned_nums
284 if entries:
285 for entry in entries:
286 code.globalstate.add_interned_num_decl(entry)
287 del entries[:]
289 def generate_cached_builtins_decls(self, env, code):
290 entries = env.global_scope().undeclared_cached_builtins
291 for entry in entries:
292 code.globalstate.add_cached_builtin_decl(entry)
293 del entries[:]
296 class StatListNode(Node):
297 # stats a list of StatNode
299 child_attrs = ["stats"]
301 def create_analysed(pos, env, *args, **kw):
302 node = StatListNode(pos, *args, **kw)
303 return node # No node-specific analysis necesarry
304 create_analysed = staticmethod(create_analysed)
306 def analyse_control_flow(self, env):
307 for stat in self.stats:
308 stat.analyse_control_flow(env)
310 def analyse_declarations(self, env):
311 #print "StatListNode.analyse_declarations" ###
312 for stat in self.stats:
313 stat.analyse_declarations(env)
315 def analyse_expressions(self, env):
316 #print "StatListNode.analyse_expressions" ###
317 for stat in self.stats:
318 stat.analyse_expressions(env)
320 def generate_function_definitions(self, env, code):
321 #print "StatListNode.generate_function_definitions" ###
322 for stat in self.stats:
323 stat.generate_function_definitions(env, code)
325 def generate_execution_code(self, code):
326 #print "StatListNode.generate_execution_code" ###
327 for stat in self.stats:
328 code.mark_pos(stat.pos)
329 stat.generate_execution_code(code)
331 def annotate(self, code):
332 for stat in self.stats:
333 stat.annotate(code)
336 class StatNode(Node):
337 #
338 # Code generation for statements is split into the following subphases:
339 #
340 # (1) generate_function_definitions
341 # Emit C code for the definitions of any structs,
342 # unions, enums and functions defined in the current
343 # scope-block.
344 #
345 # (2) generate_execution_code
346 # Emit C code for executable statements.
347 #
349 def generate_function_definitions(self, env, code):
350 pass
352 def generate_execution_code(self, code):
353 raise InternalError("generate_execution_code not implemented for %s" % \
354 self.__class__.__name__)
357 class CDefExternNode(StatNode):
358 # include_file string or None
359 # body StatNode
361 child_attrs = ["body"]
363 def analyse_declarations(self, env):
364 if self.include_file:
365 env.add_include_file(self.include_file)
366 old_cinclude_flag = env.in_cinclude
367 env.in_cinclude = 1
368 self.body.analyse_declarations(env)
369 env.in_cinclude = old_cinclude_flag
371 def analyse_expressions(self, env):
372 pass
374 def generate_execution_code(self, code):
375 pass
377 def annotate(self, code):
378 self.body.annotate(code)
381 class CDeclaratorNode(Node):
382 # Part of a C declaration.
383 #
384 # Processing during analyse_declarations phase:
385 #
386 # analyse
387 # Returns (name, type) pair where name is the
388 # CNameDeclaratorNode of the name being declared
389 # and type is the type it is being declared as.
390 #
391 # calling_convention string Calling convention of CFuncDeclaratorNode
392 # for which this is a base
394 child_attrs = []
396 calling_convention = ""
399 class CNameDeclaratorNode(CDeclaratorNode):
400 # name string The Pyrex name being declared
401 # cname string or None C name, if specified
402 # default ExprNode or None the value assigned on declaration
404 child_attrs = ['default']
406 default = None
408 def analyse(self, base_type, env, nonempty = 0):
409 if nonempty and self.name == '':
410 # May have mistaken the name for the type.
411 if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
412 error(self.pos, "Missing argument name")
413 elif base_type.is_void:
414 error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
415 else:
416 self.name = base_type.declaration_code("", for_display=1, pyrex=1)
417 base_type = py_object_type
418 self.type = base_type
419 return self, base_type
421 class CPtrDeclaratorNode(CDeclaratorNode):
422 # base CDeclaratorNode
424 child_attrs = ["base"]
426 def analyse(self, base_type, env, nonempty = 0):
427 if base_type.is_pyobject:
428 error(self.pos,
429 "Pointer base type cannot be a Python object")
430 ptr_type = PyrexTypes.c_ptr_type(base_type)
431 return self.base.analyse(ptr_type, env, nonempty = nonempty)
433 class CArrayDeclaratorNode(CDeclaratorNode):
434 # base CDeclaratorNode
435 # dimension ExprNode
437 child_attrs = ["base", "dimension"]
439 def analyse(self, base_type, env, nonempty = 0):
440 if self.dimension:
441 self.dimension.analyse_const_expression(env)
442 if not self.dimension.type.is_int:
443 error(self.dimension.pos, "Array dimension not integer")
444 size = self.dimension.result()
445 try:
446 size = int(size)
447 except ValueError:
448 # runtime constant?
449 pass
450 else:
451 size = None
452 if not base_type.is_complete():
453 error(self.pos,
454 "Array element type '%s' is incomplete" % base_type)
455 if base_type.is_pyobject:
456 error(self.pos,
457 "Array element cannot be a Python object")
458 if base_type.is_cfunction:
459 error(self.pos,
460 "Array element cannot be a function")
461 array_type = PyrexTypes.c_array_type(base_type, size)
462 return self.base.analyse(array_type, env, nonempty = nonempty)
465 class CFuncDeclaratorNode(CDeclaratorNode):
466 # base CDeclaratorNode
467 # args [CArgDeclNode]
468 # has_varargs boolean
469 # exception_value ConstNode
470 # exception_check boolean True if PyErr_Occurred check needed
471 # nogil boolean Can be called without gil
472 # with_gil boolean Acquire gil around function body
474 child_attrs = ["base", "args", "exception_value"]
476 overridable = 0
477 optional_arg_count = 0
479 def analyse(self, return_type, env, nonempty = 0):
480 if nonempty:
481 nonempty -= 1
482 func_type_args = []
483 for arg_node in self.args:
484 name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
485 name = name_declarator.name
486 if name_declarator.cname:
487 error(self.pos,
488 "Function argument cannot have C name specification")
489 # Turn *[] argument into **
490 if type.is_array:
491 type = PyrexTypes.c_ptr_type(type.base_type)
492 # Catch attempted C-style func(void) decl
493 if type.is_void:
494 error(arg_node.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
495 # if type.is_pyobject and self.nogil:
496 # error(self.pos,
497 # "Function with Python argument cannot be declared nogil")
498 func_type_args.append(
499 PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
500 if arg_node.default:
501 self.optional_arg_count += 1
502 elif self.optional_arg_count:
503 error(self.pos, "Non-default argument follows default argument")
505 if self.optional_arg_count:
506 scope = StructOrUnionScope()
507 scope.declare_var('%sn' % Naming.pyrex_prefix, PyrexTypes.c_int_type, self.pos)
508 for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
509 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
510 struct_cname = env.mangle(Naming.opt_arg_prefix, self.base.name)
511 self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
512 kind = 'struct',
513 scope = scope,
514 typedef_flag = 0,
515 pos = self.pos,
516 cname = struct_cname)
517 self.op_args_struct.defined_in_pxd = 1
518 self.op_args_struct.used = 1
520 exc_val = None
521 exc_check = 0
522 if return_type.is_pyobject \
523 and (self.exception_value or self.exception_check) \
524 and self.exception_check != '+':
525 error(self.pos,
526 "Exception clause not allowed for function returning Python object")
527 else:
528 if self.exception_value:
529 self.exception_value.analyse_const_expression(env)
530 if self.exception_check == '+':
531 exc_val_type = self.exception_value.type
532 if not exc_val_type.is_error and \
533 not exc_val_type.is_pyobject and \
534 not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
535 error(self.exception_value.pos,
536 "Exception value must be a Python exception or cdef function with no arguments.")
537 exc_val = self.exception_value
538 else:
539 exc_val = self.exception_value.result()
540 if not return_type.assignable_from(self.exception_value.type):
541 error(self.exception_value.pos,
542 "Exception value incompatible with function return type")
543 exc_check = self.exception_check
544 if return_type.is_array:
545 error(self.pos,
546 "Function cannot return an array")
547 if return_type.is_cfunction:
548 error(self.pos,
549 "Function cannot return a function")
550 func_type = PyrexTypes.CFuncType(
551 return_type, func_type_args, self.has_varargs,
552 optional_arg_count = self.optional_arg_count,
553 exception_value = exc_val, exception_check = exc_check,
554 calling_convention = self.base.calling_convention,
555 nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
556 if self.optional_arg_count:
557 func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
558 return self.base.analyse(func_type, env)
561 class CArgDeclNode(Node):
562 # Item in a function declaration argument list.
563 #
564 # base_type CBaseTypeNode
565 # declarator CDeclaratorNode
566 # not_none boolean Tagged with 'not None'
567 # default ExprNode or None
568 # default_entry Symtab.Entry Entry for the variable holding the default value
569 # default_result_code string cname or code fragment for default value
570 # is_self_arg boolean Is the "self" arg of an extension type method
571 # is_kw_only boolean Is a keyword-only argument
573 child_attrs = ["base_type", "declarator", "default"]
575 is_self_arg = 0
576 is_generic = 1
577 type = None
578 name_declarator = None
580 def analyse(self, env, nonempty = 0):
581 #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
582 if self.type is None:
583 # The parser may missinterpret names as types...
584 # We fix that here.
585 if isinstance(self.declarator, CNameDeclaratorNode) and self.declarator.name == '':
586 if nonempty:
587 self.declarator.name = self.base_type.name
588 self.base_type.name = None
589 self.base_type.is_basic_c_type = False
590 could_be_name = True
591 else:
592 could_be_name = False
593 base_type = self.base_type.analyse(env, could_be_name = could_be_name)
594 if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
595 self.declarator.name = self.base_type.arg_name
596 return self.declarator.analyse(base_type, env, nonempty = nonempty)
597 else:
598 return self.name_declarator, self.type
600 def annotate(self, code):
601 if self.default:
602 self.default.annotate(code)
605 class CBaseTypeNode(Node):
606 # Abstract base class for C base type nodes.
607 #
608 # Processing during analyse_declarations phase:
609 #
610 # analyse
611 # Returns the type.
613 pass
615 class CAnalysedBaseTypeNode(Node):
616 # type type
618 child_attrs = []
620 def analyse(self, env, could_be_name = False):
621 return self.type
623 class CSimpleBaseTypeNode(CBaseTypeNode):
624 # name string
625 # module_path [string] Qualifying name components
626 # is_basic_c_type boolean
627 # signed boolean
628 # longness integer
629 # is_self_arg boolean Is self argument of C method
631 child_attrs = []
632 arg_name = None # in case the argument name was interpreted as a type
634 def analyse(self, env, could_be_name = False):
635 # Return type descriptor.
636 #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
637 type = None
638 if self.is_basic_c_type:
639 type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name)
640 if not type:
641 error(self.pos, "Unrecognised type modifier combination")
642 elif self.name == "object" and not self.module_path:
643 type = py_object_type
644 elif self.name is None:
645 if self.is_self_arg and env.is_c_class_scope:
646 #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ###
647 type = env.parent_type
648 else:
649 type = py_object_type
650 else:
651 if self.module_path:
652 scope = env.find_imported_module(self.module_path, self.pos)
653 else:
654 scope = env
655 if scope:
656 if scope.is_c_class_scope:
657 scope = scope.global_scope()
658 entry = scope.lookup(self.name)
659 if entry and entry.is_type:
660 type = entry.type
661 elif could_be_name:
662 if self.is_self_arg and env.is_c_class_scope:
663 type = env.parent_type
664 else:
665 type = py_object_type
666 self.arg_name = self.name
667 else:
668 error(self.pos, "'%s' is not a type identifier" % self.name)
669 if type:
670 return type
671 else:
672 return PyrexTypes.error_type
674 class CBufferAccessTypeNode(CBaseTypeNode):
675 # After parsing:
676 # positional_args [ExprNode] List of positional arguments
677 # keyword_args DictNode Keyword arguments
678 # base_type_node CBaseTypeNode
680 # After analysis:
681 # type PyrexType.BufferType ...containing the right options
684 child_attrs = ["base_type_node", "positional_args",
685 "keyword_args", "dtype_node"]
687 dtype_node = None
689 def analyse(self, env, could_be_name = False):
690 base_type = self.base_type_node.analyse(env)
691 if base_type.is_error: return base_type
692 import Buffer
694 options = Buffer.analyse_buffer_options(
695 self.pos,
696 env,
697 self.positional_args,
698 self.keyword_args,
699 base_type.buffer_defaults)
701 self.type = PyrexTypes.BufferType(base_type, **options)
702 return self.type
704 class CComplexBaseTypeNode(CBaseTypeNode):
705 # base_type CBaseTypeNode
706 # declarator CDeclaratorNode
708 child_attrs = ["base_type", "declarator"]
710 def analyse(self, env, could_be_name = False):
711 base = self.base_type.analyse(env, could_be_name)
712 _, type = self.declarator.analyse(base, env)
713 return type
716 class CVarDefNode(StatNode):
717 # C variable definition or forward/extern function declaration.
718 #
719 # visibility 'private' or 'public' or 'extern'
720 # base_type CBaseTypeNode
721 # declarators [CDeclaratorNode]
722 # in_pxd boolean
723 # api boolean
724 # need_properties [entry]
725 # pxd_locals [CVarDefNode] (used for functions declared in pxd)
727 child_attrs = ["base_type", "declarators"]
728 need_properties = ()
729 pxd_locals = []
731 def analyse_declarations(self, env, dest_scope = None):
732 if not dest_scope:
733 dest_scope = env
734 self.dest_scope = dest_scope
735 base_type = self.base_type.analyse(env)
736 if (dest_scope.is_c_class_scope
737 and self.visibility == 'public'
738 and base_type.is_pyobject
739 and (base_type.is_builtin_type or base_type.is_extension_type)):
740 self.need_properties = []
741 need_property = True
742 visibility = 'private'
743 else:
744 need_property = False
745 visibility = self.visibility
747 for declarator in self.declarators:
748 name_declarator, type = declarator.analyse(base_type, env)
749 if not type.is_complete():
750 if not (self.visibility == 'extern' and type.is_array):
751 error(declarator.pos,
752 "Variable type '%s' is incomplete" % type)
753 if self.visibility == 'extern' and type.is_pyobject:
754 error(declarator.pos,
755 "Python object cannot be declared extern")
756 name = name_declarator.name
757 cname = name_declarator.cname
758 if name == '':
759 error(declarator.pos, "Missing name in declaration.")
760 return
761 if type.is_cfunction:
762 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
763 cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
764 api = self.api)
765 if entry is not None:
766 entry.pxd_locals = self.pxd_locals
767 else:
768 if self.in_pxd and self.visibility != 'extern':
769 error(self.pos,
770 "Only 'extern' C variable declaration allowed in .pxd file")
771 entry = dest_scope.declare_var(name, type, declarator.pos,
772 cname = cname, visibility = visibility, is_cdef = 1)
773 if need_property:
774 self.need_properties.append(entry)
775 entry.needs_property = 1
778 class CStructOrUnionDefNode(StatNode):
779 # name string
780 # cname string or None
781 # kind "struct" or "union"
782 # typedef_flag boolean
783 # visibility "public" or "private"
784 # in_pxd boolean
785 # attributes [CVarDefNode] or None
786 # entry Entry
788 child_attrs = ["attributes"]
790 def analyse_declarations(self, env):
791 scope = None
792 if self.attributes is not None:
793 scope = StructOrUnionScope(self.name)
794 self.entry = env.declare_struct_or_union(
795 self.name, self.kind, scope, self.typedef_flag, self.pos,
796 self.cname, visibility = self.visibility)
797 if self.attributes is not None:
798 if self.in_pxd and not env.in_cinclude:
799 self.entry.defined_in_pxd = 1
800 for attr in self.attributes:
801 attr.analyse_declarations(env, scope)
802 if self.visibility != 'extern':
803 need_typedef_indirection = False
804 for attr in scope.var_entries:
805 type = attr.type
806 while type.is_array:
807 type = type.base_type
808 if type == self.entry.type:
809 error(attr.pos, "Struct cannot contain itself as a member.")
810 if self.typedef_flag:
811 while type.is_ptr:
812 type = type.base_type
813 if type == self.entry.type:
814 need_typedef_indirection = True
815 if need_typedef_indirection:
816 # C can't handle typedef structs that refer to themselves.
817 struct_entry = self.entry
818 cname = env.new_const_cname()
819 self.entry = env.declare_typedef(self.name, struct_entry.type, self.pos, cname = self.cname, visibility='ignore')
820 struct_entry.type.typedef_flag = False
821 struct_entry.cname = struct_entry.type.cname = env.new_const_cname()
823 def analyse_expressions(self, env):
824 pass
826 def generate_execution_code(self, code):
827 pass
830 class CEnumDefNode(StatNode):
831 # name string or None
832 # cname string or None
833 # items [CEnumDefItemNode]
834 # typedef_flag boolean
835 # visibility "public" or "private"
836 # in_pxd boolean
837 # entry Entry
839 child_attrs = ["items"]
841 def analyse_declarations(self, env):
842 self.entry = env.declare_enum(self.name, self.pos,
843 cname = self.cname, typedef_flag = self.typedef_flag,
844 visibility = self.visibility)
845 if self.items is not None:
846 if self.in_pxd and not env.in_cinclude:
847 self.entry.defined_in_pxd = 1
848 for item in self.items:
849 item.analyse_declarations(env, self.entry)
851 def analyse_expressions(self, env):
852 if self.visibility == 'public':
853 self.temp = env.allocate_temp_pyobject()
854 env.release_temp(self.temp)
856 def generate_execution_code(self, code):
857 if self.visibility == 'public':
858 for item in self.entry.enum_values:
859 code.putln("%s = PyInt_FromLong(%s); %s" % (
860 self.temp,
861 item.cname,
862 code.error_goto_if_null(self.temp, item.pos)))
863 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
864 Naming.module_cname,
865 item.name,
866 self.temp,
867 code.error_goto(item.pos)))
868 code.putln("%s = 0;" % self.temp)
871 class CEnumDefItemNode(StatNode):
872 # name string
873 # cname string or None
874 # value ExprNode or None
876 child_attrs = ["value"]
878 def analyse_declarations(self, env, enum_entry):
879 if self.value:
880 self.value.analyse_const_expression(env)
881 if not self.value.type.is_int:
882 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
883 self.value.analyse_const_expression(env)
884 value = self.value.result()
885 else:
886 value = self.name
887 entry = env.declare_const(self.name, enum_entry.type,
888 value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
889 enum_entry.enum_values.append(entry)
892 class CTypeDefNode(StatNode):
893 # base_type CBaseTypeNode
894 # declarator CDeclaratorNode
895 # visibility "public" or "private"
896 # in_pxd boolean
898 child_attrs = ["base_type", "declarator"]
900 def analyse_declarations(self, env):
901 base = self.base_type.analyse(env)
902 name_declarator, type = self.declarator.analyse(base, env)
903 name = name_declarator.name
904 cname = name_declarator.cname
905 entry = env.declare_typedef(name, type, self.pos,
906 cname = cname, visibility = self.visibility)
907 if self.in_pxd and not env.in_cinclude:
908 entry.defined_in_pxd = 1
910 def analyse_expressions(self, env):
911 pass
912 def generate_execution_code(self, code):
913 pass
916 class FuncDefNode(StatNode, BlockNode):
917 # Base class for function definition nodes.
918 #
919 # return_type PyrexType
920 # #filename string C name of filename string const
921 # entry Symtab.Entry
922 # needs_closure boolean Whether or not this function has inner functions/classes/yield
923 # pxd_locals [CVarDefNode] locals defined in the pxd
925 py_func = None
926 assmt = None
927 needs_closure = False
928 pxd_locals = []
930 def analyse_default_values(self, env):
931 genv = env.global_scope()
932 for arg in self.args:
933 if arg.default:
934 if arg.is_generic:
935 if not hasattr(arg, 'default_entry'):
936 arg.default.analyse_types(env)
937 arg.default = arg.default.coerce_to(arg.type, genv)
938 if arg.default.is_literal:
939 arg.default_entry = arg.default
940 arg.default_result_code = arg.default.calculate_result_code()
941 if arg.default.type != arg.type and not arg.type.is_int:
942 arg.default_result_code = arg.type.cast_code(arg.default_result_code)
943 else:
944 arg.default.allocate_temps(genv)
945 arg.default_entry = genv.add_default_value(arg.type)
946 arg.default_entry.used = 1
947 arg.default_result_code = arg.default_entry.cname
948 else:
949 error(arg.pos,
950 "This argument cannot have a default value")
951 arg.default = None
953 def need_gil_acquisition(self, lenv):
954 return 0
956 def create_local_scope(self, env):
957 genv = env
958 while env.is_py_class_scope or env.is_c_class_scope:
959 env = env.outer_scope
960 if self.needs_closure:
961 lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv)
962 else:
963 lenv = LocalScope(name = self.entry.name, outer_scope = genv)
964 lenv.return_type = self.return_type
965 type = self.entry.type
966 if type.is_cfunction:
967 lenv.nogil = type.nogil and not type.with_gil
968 self.local_scope = lenv
969 return lenv
971 def generate_function_definitions(self, env, code):
972 import Buffer
974 lenv = self.local_scope
976 is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
977 self.entry.scope.is_c_class_scope)
979 # Generate C code for header and body of function
980 code.enter_cfunc_scope()
981 code.return_from_error_cleanup_label = code.new_label()
983 # ----- Top-level constants used by this function
984 code.mark_pos(self.pos)
985 self.generate_interned_num_decls(lenv, code)
986 self.generate_interned_string_decls(lenv, code)
987 self.generate_py_string_decls(lenv, code)
988 self.generate_cached_builtins_decls(lenv, code)
989 #code.putln("")
990 #code.put_var_declarations(lenv.const_entries, static = 1)
991 self.generate_const_definitions(lenv, code)
992 # ----- Function header
993 code.putln("")
994 if self.py_func:
995 self.py_func.generate_function_header(code,
996 with_pymethdef = env.is_py_class_scope,
997 proto_only=True)
998 self.generate_function_header(code,
999 with_pymethdef = env.is_py_class_scope)
1000 # ----- Local variable declarations
1001 lenv.mangle_closure_cnames(Naming.cur_scope_cname)
1002 self.generate_argument_declarations(lenv, code)
1003 if self.needs_closure:
1004 code.putln("/* TODO: declare and create scope object */")
1005 code.put_var_declarations(lenv.var_entries)
1006 init = ""
1007 if not self.return_type.is_void:
1008 code.putln(
1009 "%s%s;" %
1010 (self.return_type.declaration_code(
1011 Naming.retval_cname),
1012 init))
1013 tempvardecl_code = code.insertion_point()
1014 self.generate_keyword_list(code)
1015 # ----- Extern library function declarations
1016 lenv.generate_library_function_declarations(code)
1017 # ----- GIL acquisition
1018 acquire_gil = self.need_gil_acquisition(lenv)
1019 if acquire_gil:
1020 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
1021 # ----- Automatic lead-ins for certain special functions
1022 if is_getbuffer_slot:
1023 self.getbuffer_init(code)
1024 # ----- Fetch arguments
1025 self.generate_argument_parsing_code(env, code)
1026 # If an argument is assigned to in the body, we must
1027 # incref it to properly keep track of refcounts.
1028 for entry in lenv.arg_entries:
1029 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1030 code.put_var_incref(entry)
1031 # ----- Initialise local variables
1032 for entry in lenv.var_entries:
1033 if entry.type.is_pyobject and entry.init_to_none and entry.used:
1034 code.put_init_var_to_py_none(entry)
1035 # ----- Initialise local buffer auxiliary variables
1036 for entry in lenv.var_entries + lenv.arg_entries:
1037 if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
1038 code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
1039 # ----- Check and convert arguments
1040 self.generate_argument_type_tests(code)
1041 # ----- Acquire buffer arguments
1042 for entry in lenv.arg_entries:
1043 if entry.type.is_buffer:
1044 Buffer.put_acquire_arg_buffer(entry, code, self.pos)
1045 # ----- Function body
1046 self.body.generate_execution_code(code)
1047 # ----- Default return value
1048 code.putln("")
1049 if self.return_type.is_pyobject:
1050 #if self.return_type.is_extension_type:
1051 # lhs = "(PyObject *)%s" % Naming.retval_cname
1052 #else:
1053 lhs = Naming.retval_cname
1054 code.put_init_to_py_none(lhs, self.return_type)
1055 else:
1056 val = self.return_type.default_value
1057 if val:
1058 code.putln("%s = %s;" % (Naming.retval_cname, val))
1059 # ----- Error cleanup
1060 if code.error_label in code.labels_used:
1061 code.put_goto(code.return_label)
1062 code.put_label(code.error_label)
1063 # cleanup temps the old way
1064 code.put_var_xdecrefs(lenv.temp_entries)
1065 # cleanup temps the new way
1066 for cname, type in code.funcstate.all_managed_temps():
1067 code.put_xdecref(cname, type)
1069 # Clean up buffers -- this calls a Python function
1070 # so need to save and restore error state
1071 buffers_present = len(lenv.buffer_entries) > 0
1072 if buffers_present:
1073 code.globalstate.use_utility_code(restore_exception_utility_code)
1074 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
1075 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
1076 for entry in lenv.buffer_entries:
1077 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1078 #code.putln("%s = 0;" % entry.cname)
1079 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
1081 err_val = self.error_value()
1082 exc_check = self.caller_will_check_exceptions()
1083 if err_val is not None or exc_check:
1084 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1085 else:
1086 warning(self.entry.pos, "Unraisable exception in function '%s'." \
1087 % self.entry.qualified_name, 0)
1088 code.putln(
1089 '__Pyx_WriteUnraisable("%s");' %
1090 self.entry.qualified_name)
1091 env.use_utility_code(unraisable_exception_utility_code)
1092 env.use_utility_code(restore_exception_utility_code)
1093 default_retval = self.return_type.default_value
1094 if err_val is None and default_retval:
1095 err_val = default_retval
1096 if err_val is not None:
1097 code.putln(
1098 "%s = %s;" % (
1099 Naming.retval_cname,
1100 err_val))
1102 if is_getbuffer_slot:
1103 self.getbuffer_error_cleanup(code)
1105 # If we are using the non-error cleanup section we should
1106 # jump past it if we have an error. The if-test below determine
1107 # whether this section is used.
1108 if buffers_present or is_getbuffer_slot:
1109 code.put_goto(code.return_from_error_cleanup_label)
1112 # ----- Non-error return cleanup
1113 # If you add anything here, remember to add a condition to the
1114 # if-test above in the error block (so that it can jump past this
1115 # block).
1116 code.put_label(code.return_label)
1117 for entry in lenv.buffer_entries:
1118 if entry.used:
1119 code.putln("%s;" % Buffer.get_release_buffer_code(entry))
1120 if is_getbuffer_slot:
1121 self.getbuffer_normal_cleanup(code)
1122 # ----- Return cleanup for both error and no-error return
1123 code.put_label(code.return_from_error_cleanup_label)
1124 if not Options.init_local_none:
1125 for entry in lenv.var_entries:
1126 if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
1127 entry.xdecref_cleanup = 1
1128 code.put_var_decrefs(lenv.var_entries, used_only = 1)
1129 # Decref any increfed args
1130 for entry in lenv.arg_entries:
1131 if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
1132 code.put_var_decref(entry)
1133 if acquire_gil:
1134 code.putln("PyGILState_Release(_save);")
1135 # code.putln("/* TODO: decref scope object */")
1136 # ----- Return
1137 if not self.return_type.is_void:
1138 code.putln("return %s;" % Naming.retval_cname)
1139 code.putln("}")
1140 # ----- Go back and insert temp variable declarations
1141 tempvardecl_code.put_var_declarations(lenv.temp_entries)
1142 tempvardecl_code.put_temp_declarations(code.funcstate)
1143 # ----- Python version
1144 code.exit_cfunc_scope()
1145 if self.py_func:
1146 self.py_func.generate_function_definitions(env, code)
1147 self.generate_wrapper_functions(code)
1149 def declare_argument(self, env, arg):
1150 if arg.type.is_void:
1151 error(arg.pos, "Invalid use of 'void'")
1152 elif not arg.type.is_complete() and not arg.type.is_array:
1153 error(arg.pos,
1154 "Argument type '%s' is incomplete" % arg.type)
1155 return env.declare_arg(arg.name, arg.type, arg.pos)
1157 def generate_wrapper_functions(self, code):
1158 pass
1160 def generate_execution_code(self, code):
1161 # Evaluate and store argument default values
1162 for arg in self.args:
1163 default = arg.default
1164 if default:
1165 if not default.is_literal:
1166 default.generate_evaluation_code(code)
1167 default.make_owned_reference(code)
1168 code.putln(
1169 "%s = %s;" % (
1170 arg.default_entry.cname,
1171 default.result_as(arg.default_entry.type)))
1172 if default.is_temp and default.type.is_pyobject:
1173 code.putln(
1174 "%s = 0;" %
1175 default.result())
1176 # For Python class methods, create and store function object
1177 if self.assmt:
1178 self.assmt.generate_execution_code(code)
1180 #
1181 # Special code for the __getbuffer__ function
1182 #
1183 def getbuffer_init(self, code):
1184 info = self.local_scope.arg_entries[1].cname
1185 # Python 3.0 betas have a bug in memoryview which makes it call
1186 # getbuffer with a NULL parameter. For now we work around this;
1187 # the following line should be removed when this bug is fixed.
1188 code.putln("if (%s == NULL) return 0;" % info)
1189 code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
1191 def getbuffer_error_cleanup(self, code):
1192 info = self.local_scope.arg_entries[1].cname
1193 code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
1194 (info, info))
1196 def getbuffer_normal_cleanup(self, code):
1197 info = self.local_scope.arg_entries[1].cname
1198 code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
1199 (info, info))
1201 class CFuncDefNode(FuncDefNode):
1202 # C function definition.
1203 #
1204 # modifiers ['inline']
1205 # visibility 'private' or 'public' or 'extern'
1206 # base_type CBaseTypeNode
1207 # declarator CDeclaratorNode
1208 # body StatListNode
1209 # api boolean
1210 #
1211 # with_gil boolean Acquire GIL around body
1212 # type CFuncType
1213 # py_func wrapper for calling from Python
1214 # overridable whether or not this is a cpdef function
1215 # inline_in_pxd whether this is an inline function in a pxd file
1217 child_attrs = ["base_type", "declarator", "body", "py_func"]
1219 inline_in_pxd = False
1221 def unqualified_name(self):
1222 return self.entry.name
1224 def analyse_declarations(self, env):
1225 if 'locals' in env.directives:
1226 directive_locals = env.directives['locals']
1227 else:
1228 directive_locals = {}
1229 self.directive_locals = directive_locals
1230 base_type = self.base_type.analyse(env)
1231 # The 2 here is because we need both function and argument names.
1232 name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
1233 if not type.is_cfunction:
1234 error(self.pos,
1235 "Suite attached to non-function declaration")
1236 # Remember the actual type according to the function header
1237 # written here, because the type in the symbol table entry
1238 # may be different if we're overriding a C method inherited
1239 # from the base type of an extension type.
1240 self.type = type
1241 type.is_overridable = self.overridable
1242 declarator = self.declarator
1243 while not hasattr(declarator, 'args'):
1244 declarator = declarator.base
1245 self.args = declarator.args
1246 for formal_arg, type_arg in zip(self.args, type.args):
1247 formal_arg.type = type_arg.type
1248 formal_arg.name = type_arg.name
1249 formal_arg.cname = type_arg.cname
1250 name = name_declarator.name
1251 cname = name_declarator.cname
1252 self.entry = env.declare_cfunction(
1253 name, type, self.pos,
1254 cname = cname, visibility = self.visibility,
1255 defining = self.body is not None,
1256 api = self.api, modifiers = self.modifiers)
1257 self.entry.inline_func_in_pxd = self.inline_in_pxd
1258 self.return_type = type.return_type
1260 if self.overridable:
1261 import ExprNodes
1262 py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
1263 self.py_func = DefNode(pos = self.pos,
1264 name = self.entry.name,
1265 args = self.args,
1266 star_arg = None,
1267 starstar_arg = None,
1268 doc = self.doc,
1269 body = py_func_body,
1270 is_wrapper = 1)
1271 self.py_func.is_module_scope = env.is_module_scope
1272 self.py_func.analyse_declarations(env)
1273 self.entry.as_variable = self.py_func.entry
1274 # Reset scope entry the above cfunction
1275 env.entries[name] = self.entry
1276 self.py_func.interned_attr_cname = env.intern_identifier(
1277 self.py_func.entry.name)
1278 if not env.is_module_scope or Options.lookup_module_cpdef:
1279 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
1280 self.body = StatListNode(self.pos, stats=[self.override, self.body])
1282 def call_self_node(self, omit_optional_args=0, is_module_scope=0):
1283 import ExprNodes
1284 args = self.type.args
1285 if omit_optional_args:
1286 args = args[:len(args) - self.type.optional_arg_count]
1287 arg_names = [arg.name for arg in args]
1288 if is_module_scope:
1289 cfunc = ExprNodes.NameNode(self.pos, name=self.entry.name)
1290 else:
1291 self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
1292 cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.entry.name)
1293 skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
1294 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)
1295 return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
1297 def declare_arguments(self, env):
1298 for arg in self.type.args:
1299 if not arg.name:
1300 error(arg.pos, "Missing argument name")
1301 self.declare_argument(env, arg)
1303 def need_gil_acquisition(self, lenv):
1304 type = self.type
1305 with_gil = self.type.with_gil
1306 if type.nogil and not with_gil:
1307 if type.return_type.is_pyobject:
1308 error(self.pos,
1309 "Function with Python return type cannot be declared nogil")
1310 for entry in lenv.var_entries + lenv.temp_entries:
1311 if entry.type.is_pyobject:
1312 error(self.pos, "Function declared nogil has Python locals or temporaries")
1313 return with_gil
1315 def analyse_expressions(self, env):
1316 self.analyse_default_values(env)
1317 if self.overridable:
1318 self.py_func.analyse_expressions(env)
1320 def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
1321 arg_decls = []
1322 type = self.type
1323 visibility = self.entry.visibility
1324 for arg in type.args[:len(type.args)-type.optional_arg_count]:
1325 arg_decls.append(arg.declaration_code())
1326 if with_dispatch and self.overridable:
1327 arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname))
1328 if type.optional_arg_count and with_opt_args:
1329 arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
1330 if type.has_varargs:
1331 arg_decls.append("...")
1332 if not arg_decls:
1333 arg_decls = ["void"]
1334 if cname is None:
1335 cname = self.entry.func_cname
1336 entity = type.function_header_code(cname, string.join(arg_decls, ", "))
1337 if visibility == 'public':
1338 dll_linkage = "DL_EXPORT"
1339 else:
1340 dll_linkage = None
1341 header = self.return_type.declaration_code(entity,
1342 dll_linkage = dll_linkage)
1343 if visibility == 'extern':
1344 storage_class = "%s " % Naming.extern_c_macro
1345 elif visibility == 'public':
1346 storage_class = ""
1347 else:
1348 storage_class = "static "
1349 code.putln("%s%s %s {" % (
1350 storage_class,
1351 ' '.join(self.modifiers).upper(), # macro forms
1352 header))
1354 def generate_argument_declarations(self, env, code):
1355 for arg in self.args:
1356 if arg.default:
1357 code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
1359 def generate_keyword_list(self, code):
1360 pass
1362 def generate_argument_parsing_code(self, env, code):
1363 i = 0
1364 if self.type.optional_arg_count:
1365 code.putln('if (%s) {' % Naming.optional_args_cname)
1366 for arg in self.args:
1367 if arg.default:
1368 code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
1369 declarator = arg.declarator
1370 while not hasattr(declarator, 'name'):
1371 declarator = declarator.base
1372 code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
1373 i += 1
1374 for _ in range(self.type.optional_arg_count):
1375 code.putln('}')
1376 code.putln('}')
1378 def generate_argument_conversion_code(self, code):
1379 pass
1381 def generate_argument_type_tests(self, code):
1382 # Generate type tests for args whose type in a parent
1383 # class is a supertype of the declared type.
1384 for arg in self.type.args:
1385 if arg.needs_type_test:
1386 self.generate_arg_type_test(arg, code)
1388 def generate_arg_type_test(self, arg, code):
1389 # Generate type test for one argument.
1390 if arg.type.typeobj_is_available():
1391 typeptr_cname = arg.type.typeptr_cname
1392 arg_code = "((PyObject *)%s)" % arg.cname
1393 code.putln(
1394 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
1395 arg_code,
1396 typeptr_cname,
1397 not arg.not_none,
1398 arg.name,
1399 type.is_builtin_type,
1400 code.error_goto(arg.pos)))
1401 else:
1402 error(arg.pos, "Cannot test type of extern C class "
1403 "without type object name specification")
1405 def error_value(self):
1406 if self.return_type.is_pyobject:
1407 return "0"
1408 else:
1409 #return None
1410 return self.entry.type.exception_value
1412 def caller_will_check_exceptions(self):
1413 return self.entry.type.exception_check
1415 def generate_wrapper_functions(self, code):
1416 # If the C signature of a function has changed, we need to generate
1417 # wrappers to put in the slots here.
1418 k = 0
1419 entry = self.entry
1420 func_type = entry.type
1421 while entry.prev_entry is not None:
1422 k += 1
1423 entry = entry.prev_entry
1424 entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
1425 code.putln()
1426 self.generate_function_header(code,
1427 0,
1428 with_dispatch = entry.type.is_overridable,
1429 with_opt_args = entry.type.optional_arg_count,
1430 cname = entry.func_cname)
1431 if not self.return_type.is_void:
1432 code.put('return ')
1433 args = self.type.args
1434 arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
1435 if entry.type.is_overridable:
1436 arglist.append(Naming.skip_dispatch_cname)
1437 elif func_type.is_overridable:
1438 arglist.append('0')
1439 if entry.type.optional_arg_count:
1440 arglist.append(Naming.optional_args_cname)
1441 elif func_type.optional_arg_count:
1442 arglist.append('NULL')
1443 code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
1444 code.putln('}')
1447 class PyArgDeclNode(Node):
1448 # Argument which must be a Python object (used
1449 # for * and ** arguments).
1450 #
1451 # name string
1452 # entry Symtab.Entry
1453 child_attrs = []
1456 class DecoratorNode(Node):
1457 # A decorator
1458 #
1459 # decorator NameNode or CallNode
1460 child_attrs = ['decorator']
1463 class DefNode(FuncDefNode):
1464 # A Python function definition.
1465 #
1466 # name string the Python name of the function
1467 # decorators [DecoratorNode] list of decorators
1468 # args [CArgDeclNode] formal arguments
1469 # star_arg PyArgDeclNode or None * argument
1470 # starstar_arg PyArgDeclNode or None ** argument
1471 # doc EncodedString or None
1472 # body StatListNode
1473 #
1474 # The following subnode is constructed internally
1475 # when the def statement is inside a Python class definition.
1476 #
1477 # assmt AssignmentNode Function construction/assignment
1479 child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
1481 assmt = None
1482 num_kwonly_args = 0
1483 num_required_kw_args = 0
1484 reqd_kw_flags_cname = "0"
1485 is_wrapper = 0
1486 decorators = None
1487 entry = None
1490 def __init__(self, pos, **kwds):
1491 FuncDefNode.__init__(self, pos, **kwds)
1492 k = rk = r = 0
1493 for arg in self.args:
1494 if arg.kw_only:
1495 k += 1
1496 if not arg.default:
1497 rk += 1
1498 if not arg.default:
1499 r += 1
1500 self.num_kwonly_args = k
1501 self.num_required_kw_args = rk
1502 self.num_required_args = r
1504 def as_cfunction(self, cfunc=None, scope=None):
1505 if self.star_arg:
1506 error(self.star_arg.pos, "cdef function cannot have star argument")
1507 if self.starstar_arg:
1508 error(self.starstar_arg.pos, "cdef function cannot have starstar argument")
1509 if cfunc is None:
1510 cfunc_args = []
1511 for formal_arg in self.args:
1512 name_declarator, type = formal_arg.analyse(scope, nonempty=1)
1513 cfunc_args.append(PyrexTypes.CFuncTypeArg(name = name_declarator.name,
1514 cname = None,
1515 type = py_object_type,
1516 pos = formal_arg.pos))
1517 cfunc_type = PyrexTypes.CFuncType(return_type = py_object_type,
1518 args = cfunc_args,
1519 has_varargs = False,
1520 exception_value = None,
1521 exception_check = False,
1522 nogil = False,
1523 with_gil = False,
1524 is_overridable = True)
1525 cfunc = CVarDefNode(self.pos, type=cfunc_type, pxd_locals=[])
1526 else:
1527 cfunc_type = cfunc.type
1528 if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
1529 error(self.pos, "wrong number of arguments")
1530 error(declarator.pos, "previous declaration here")
1531 for formal_arg, type_arg in zip(self.args, cfunc_type.args):
1532 name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
1533 if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
1534 formal_arg.type = type_arg.type
1535 formal_arg.name_declarator = name_declarator
1536 import ExprNodes
1537 if cfunc_type.exception_value is None:
1538 exception_value = None
1539 else:
1540 exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
1541 declarator = CFuncDeclaratorNode(self.pos,
1542 base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
1543 args = self.args,
1544 has_varargs = False,
1545 exception_check = cfunc_type.exception_check,
1546 exception_value = exception_value,
1547 with_gil = cfunc_type.with_gil,
1548 nogil = cfunc_type.nogil)
1549 return CFuncDefNode(self.pos,
1550 modifiers = [],
1551 base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
1552 declarator = declarator,
1553 body = self.body,
1554 doc = self.doc,
1555 overridable = cfunc_type.is_overridable,
1556 type = cfunc_type,
1557 with_gil = cfunc_type.with_gil,
1558 nogil = cfunc_type.nogil,
1559 visibility = 'private',
1560 api = False,
1561 pxd_locals = cfunc.pxd_locals)
1563 def analyse_declarations(self, env):
1564 if 'locals' in env.directives:
1565 directive_locals = env.directives['locals']
1566 else:
1567 directive_locals = {}
1568 self.directive_locals = directive_locals
1569 for arg in self.args:
1570 if hasattr(arg, 'name'):
1571 type = arg.type
1572 name_declarator = None
1573 else:
1574 base_type = arg.base_type.analyse(env)
1575 name_declarator, type = \
1576 arg.declarator.analyse(base_type, env)
1577 arg.name = name_declarator.name
1578 if arg.name in directive_locals:
1579 type_node = directive_locals[arg.name]
1580 other_type = type_node.analyse_as_type(env)
1581 if other_type is None:
1582 error(type_node.pos, "Not a type")
1583 elif (type is not PyrexTypes.py_object_type
1584 and not type.same_as(other_type)):
1585 error(arg.base_type.pos, "Signature does not agree with previous declaration")
1586 error(type_node.pos, "Previous declaration here")
1587 else:
1588 type = other_type
1589 if name_declarator and name_declarator.cname:
1590 error(self.pos,
1591 "Python function argument cannot have C name specification")
1592 arg.type = type.as_argument_type()
1593 arg.hdr_type = None
1594 arg.needs_conversion = 0
1595 arg.needs_type_test = 0
1596 arg.is_generic = 1
1597 if arg.not_none and not arg.type.is_extension_type:
1598 error(self.pos,
1599 "Only extension type arguments can have 'not None'")
1600 self.declare_pyfunction(env)
1601 self.analyse_signature(env)
1602 self.return_type = self.entry.signature.return_type()
1604 def analyse_signature(self, env):
1605 any_type_tests_needed = 0
1606 # Use the simpler calling signature for zero- and one-argument functions.
1607 if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
1608 if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
1609 if len(self.args) == 0:
1610 self.entry.signature = TypeSlots.pyfunction_noargs
1611 elif len(self.args) == 1:
1612 if self.args[0].default is None and not self.args[0].kw_only:
1613 self.entry.signature = TypeSlots.pyfunction_onearg
1614 elif self.entry.signature is TypeSlots.pymethod_signature:
1615 if len(self.args) == 1:
1616 self.entry.signature = TypeSlots.unaryfunc
1617 elif len(self.args) == 2:
1618 if self.args[1].default is None and not self.args[1].kw_only:
1619 self.entry.signature = TypeSlots.ibinaryfunc
1620 elif self.entry.is_special:
1621 self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
1622 sig = self.entry.signature
1623 nfixed = sig.num_fixed_args()
1624 for i in range(nfixed):
1625 if i < len(self.args):
1626 arg = self.args[i]
1627 arg.is_generic = 0
1628 if sig.is_self_arg(i):
1629 arg.is_self_arg = 1
1630 arg.hdr_type = arg.type = env.parent_type
1631 arg.needs_conversion = 0
1632 else:
1633 arg.hdr_type = sig.fixed_arg_type(i)
1634 if not arg.type.same_as(arg.hdr_type):
1635 if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
1636 arg.needs_type_test = 1
1637 any_type_tests_needed = 1
1638 else:
1639 arg.needs_conversion = 1
1640 if arg.needs_conversion:
1641 arg.hdr_cname = Naming.arg_prefix + arg.name
1642 else:
1643 arg.hdr_cname = Naming.var_prefix + arg.name
1644 else:
1645 self.bad_signature()
1646 return
1647 if nfixed < len(self.args):
1648 if not sig.has_generic_args:
1649 self.bad_signature()
1650 for arg in self.args:
1651 if arg.is_generic and \
1652 (arg.type.is_extension_type or arg.type.is_builtin_type):
1653 arg.needs_type_test = 1
1654 any_type_tests_needed = 1
1655 elif arg.type is PyrexTypes.c_py_ssize_t_type:
1656 # Want to use __index__ rather than __int__ method
1657 # that PyArg_ParseTupleAndKeywords calls
1658 arg.needs_conversion = 1
1659 arg.hdr_type = PyrexTypes.py_object_type
1660 arg.hdr_cname = Naming.arg_prefix + arg.name
1661 if any_type_tests_needed:
1662 env.use_utility_code(arg_type_test_utility_code)
1664 def bad_signature(self):
1665 sig = self.entry.signature
1666 expected_str = "%d" % sig.num_fixed_args()
1667 if sig.has_generic_args:
1668 expected_str = expected_str + " or more"
1669 name = self.name
1670 if name.startswith("__") and name.endswith("__"):
1671 desc = "Special method"
1672 else:
1673 desc = "Method"
1674 error(self.pos,
1675 "%s %s has wrong number of arguments "
1676 "(%d declared, %s expected)" % (
1677 desc, self.name, len(self.args), expected_str))
1679 def signature_has_nongeneric_args(self):
1680 argcount = len(self.args)
1681 if argcount == 0 or (argcount == 1 and self.args[0].is_self_arg):
1682 return 0
1683 return 1
1685 def signature_has_generic_args(self):
1686 return self.entry.signature.has_generic_args
1688 def declare_pyfunction(self, env):
1689 #print "DefNode.declare_pyfunction:", self.name, "in", env ###
1690 name = self.name
1691 entry = env.lookup_here(self.name)
1692 if entry and entry.type.is_cfunction and not self.is_wrapper:
1693 warning(self.pos, "Overriding cdef method with def method.", 5)
1694 entry = env.declare_pyfunction(self.name, self.pos)
1695 self.entry = entry
1696 prefix = env.scope_prefix
1697 entry.func_cname = \
1698 Naming.pyfunc_prefix + prefix + name
1699 entry.pymethdef_cname = \
1700 Naming.pymethdef_prefix + prefix + name
1701 if Options.docstrings:
1702 entry.doc = embed_position(self.pos, self.doc)
1703 entry.doc_cname = \
1704 Naming.funcdoc_prefix + prefix + name
1705 else:
1706 entry.doc = None
1708 def declare_arguments(self, env):
1709 for arg in self.args:
1710 if not arg.name:
1711 error(arg.pos, "Missing argument name")
1712 if arg.needs_conversion:
1713 arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
1714 env.control_flow.set_state((), (arg.name, 'source'), 'arg')
1715 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1716 if arg.type.is_pyobject:
1717 arg.entry.init = "0"
1718 arg.entry.init_to_none = 0
1719 else:
1720 arg.entry = self.declare_argument(env, arg)
1721 arg.entry.used = 1
1722 arg.entry.is_self_arg = arg.is_self_arg
1723 if not arg.is_self_arg:
1724 arg.name_entry = env.get_string_const(
1725 arg.name, identifier = True)
1726 env.add_py_string(arg.name_entry, identifier = True)
1727 if arg.hdr_type:
1728 if arg.is_self_arg or \
1729 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
1730 arg.entry.is_declared_generic = 1
1731 self.declare_python_arg(env, self.star_arg)
1732 self.declare_python_arg(env, self.starstar_arg)
1734 def declare_python_arg(self, env, arg):
1735 if arg:
1736 entry = env.declare_var(arg.name,
1737 PyrexTypes.py_object_type, arg.pos)
1738 entry.used = 1
1739 entry.init = "0"
1740 entry.init_to_none = 0
1741 entry.xdecref_cleanup = 1
1742 arg.entry = entry
1743 env.control_flow.set_state((), (arg.name, 'initalized'), True)
1745 def analyse_expressions(self, env):
1746 self.analyse_default_values(env)
1747 if env.is_py_class_scope:
1748 self.synthesize_assignment_node(env)
1750 def synthesize_assignment_node(self, env):
1751 import ExprNodes
1752 self.assmt = SingleAssignmentNode(self.pos,
1753 lhs = ExprNodes.NameNode(self.pos, name = self.name),
1754 rhs = ExprNodes.UnboundMethodNode(self.pos,
1755 class_cname = env.class_obj_cname,
1756 function = ExprNodes.PyCFunctionNode(self.pos,
1757 pymethdef_cname = self.entry.pymethdef_cname)))
1758 self.assmt.analyse_declarations(env)
1759 self.assmt.analyse_expressions(env)
1761 def generate_function_header(self, code, with_pymethdef, proto_only=0):
1762 arg_code_list = []
1763 sig = self.entry.signature
1764 if sig.has_dummy_arg:
1765 arg_code_list.append(
1766 "PyObject *%s" % Naming.self_cname)
1767 for arg in self.args:
1768 if not arg.is_generic:
1769 if arg.is_self_arg:
1770 arg_code_list.append("PyObject *%s" % arg.hdr_cname)
1771 else:
1772 arg_code_list.append(
1773 arg.hdr_type.declaration_code(arg.hdr_cname))
1774 if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
1775 arg_code_list.append("PyObject *unused")
1776 if sig.has_generic_args:
1777 arg_code_list.append(
1778 "PyObject *%s, PyObject *%s"
1779 % (Naming.args_cname, Naming.kwds_cname))
1780 arg_code = ", ".join(arg_code_list)
1781 dc = self.return_type.declaration_code(self.entry.func_cname)
1782 header = "static %s(%s)" % (dc, arg_code)
1783 code.putln("%s; /*proto*/" % header)
1784 if proto_only:
1785 return
1786 if self.entry.doc and Options.docstrings:
1787 docstr = self.entry.doc
1788 if not isinstance(docstr, str):
1789 docstr = docstr.utf8encode()
1790 code.putln(
1791 'static char %s[] = "%s";' % (
1792 self.entry.doc_cname,
1793 split_docstring(escape_byte_string(docstr))))
1794 if with_pymethdef:
1795 code.put(
1796 "static PyMethodDef %s = " %
1797 self.entry.pymethdef_cname)
1798 code.put_pymethoddef(self.entry, ";")
1799 code.putln("%s {" % header)
1801 def generate_argument_declarations(self, env, code):
1802 for arg in self.args:
1803 if arg.is_generic: # or arg.needs_conversion:
1804 if arg.needs_conversion:
1805 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
1806 else:
1807 code.put_var_declaration(arg.entry)
1809 def generate_keyword_list(self, code):
1810 if self.signature_has_generic_args() and \
1811 self.signature_has_nongeneric_args():
1812 code.put(
1813 "static PyObject **%s[] = {" %
1814 Naming.pykwdlist_cname)
1815 for arg in self.args:
1816 if arg.is_generic:
1817 code.put('&%s,' % arg.name_entry.pystring_cname)
1818 code.putln("0};")
1820 def generate_argument_parsing_code(self, env, code):
1821 # Generate PyArg_ParseTuple call for generic
1822 # arguments, if any.
1823 if self.entry.signature.has_dummy_arg:
1824 # get rid of unused argument warning
1825 code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
1827 old_error_label = code.new_error_label()
1828 our_error_label = code.error_label
1829 end_label = code.new_label("argument_unpacking_done")
1831 has_kwonly_args = self.num_kwonly_args > 0
1832 has_star_or_kw_args = self.star_arg is not None \
1833 or self.starstar_arg is not None or has_kwonly_args
1835 if not self.signature_has_generic_args():
1836 if has_star_or_kw_args:
1837 error(self.pos, "This method cannot have * or keyword arguments")
1838 self.generate_argument_conversion_code(code)
1840 elif not self.signature_has_nongeneric_args():
1841 # func(*args) or func(**kw) or func(*args, **kw)
1842 self.generate_stararg_copy_code(code)
1844 else:
1845 positional_args = []
1846 kw_only_args = []
1847 default_seen = 0
1848 for arg in self.args:
1849 arg_entry = arg.entry
1850 if arg.is_generic:
1851 if arg.default:
1852 code.putln(
1853 "%s = %s;" % (
1854 arg_entry.cname,
1855 arg.default_result_code))
1856 default_seen = 1
1857 if not arg.is_self_arg:
1858 if arg.kw_only:
1859 kw_only_args.append(arg)
1860 else:
1861 positional_args.append(arg)
1862 elif arg.kw_only:
1863 kw_only_args.append(arg)
1864 default_seen = 1
1865 elif default_seen:
1866 error(arg.pos, "Non-default argument following default argument")
1867 elif not arg.is_self_arg:
1868 positional_args.append(arg)
1869 if arg.needs_conversion:
1870 format = arg.hdr_type.parsetuple_format
1871 else:
1872 format = arg_entry.type.parsetuple_format
1873 if not format:
1874 error(arg.pos,
1875 "Cannot convert Python object argument to type '%s' (when parsing input arguments)"
1876 % arg.type)
1878 self.generate_tuple_and_keyword_parsing_code(
1879 positional_args, kw_only_args, end_label, code)
1881 code.error_label = old_error_label
1882 if code.label_used(our_error_label):
1883 if not code.label_used(end_label):
1884 code.put_goto(end_label)
1885 code.put_label(our_error_label)
1886 if has_star_or_kw_args:
1887 self.generate_arg_decref(self.star_arg, code)
1888 if self.starstar_arg:
1889 if self.starstar_arg.entry.xdecref_cleanup:
1890 code.put_var_xdecref(self.starstar_arg.entry)
1891 else:
1892 code.put_var_decref(self.starstar_arg.entry)
1893 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
1894 code.putln("return %s;" % self.error_value())
1895 if code.label_used(end_label):
1896 code.put_label(end_label)
1898 def generate_arg_assignment(self, arg, item, code):
1899 if arg.type.is_pyobject:
1900 if arg.is_generic:
1901 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
1902 code.putln("%s = %s;" % (arg.entry.cname, item))
1903 else:
1904 func = arg.type.from_py_function
1905 if func:
1906 code.putln("%s = %s(%s); %s" % (
1907 arg.entry.cname,
1908 func,
1909 item,
1910 code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
1911 else:
1912 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
1914 def generate_arg_xdecref(self, arg, code):
1915 if arg:
1916 code.put_var_xdecref(arg.entry)
1918 def generate_arg_decref(self, arg, code):
1919 if arg:
1920 code.put_var_decref(arg.entry)
1922 def generate_stararg_copy_code(self, code):
1923 if not self.star_arg:
1924 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1925 code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > 0)) {" %
1926 Naming.args_cname)
1927 code.put('__Pyx_RaiseArgtupleInvalid("%s", 1, 0, 0, PyTuple_GET_SIZE(%s)); return %s;' % (
1928 self.name.utf8encode(), Naming.args_cname, self.error_value()))
1929 code.putln("}")
1931 code.globalstate.use_utility_code(keyword_string_check_utility_code)
1933 if self.starstar_arg:
1934 if self.star_arg:
1935 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
1936 else:
1937 kwarg_check = "%s" % Naming.kwds_cname
1938 else:
1939 kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
1940 Naming.kwds_cname, Naming.kwds_cname)
1941 code.putln(
1942 "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
1943 kwarg_check, Naming.kwds_cname, self.name,
1944 bool(self.starstar_arg), self.error_value()))
1946 if self.starstar_arg:
1947 code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
1948 self.starstar_arg.entry.cname,
1949 Naming.kwds_cname,
1950 Naming.kwds_cname))
1951 code.putln("if (unlikely(!%s)) return %s;" % (
1952 self.starstar_arg.entry.cname, self.error_value()))
1953 self.starstar_arg.entry.xdecref_cleanup = 0
1955 if self.star_arg:
1956 code.put_incref(Naming.args_cname, py_object_type)
1957 code.putln("%s = %s;" % (
1958 self.star_arg.entry.cname,
1959 Naming.args_cname))
1960 self.star_arg.entry.xdecref_cleanup = 0
1962 def generate_tuple_and_keyword_parsing_code(self, positional_args,
1963 kw_only_args, success_label, code):
1964 argtuple_error_label = code.new_label("argtuple_error")
1966 min_positional_args = self.num_required_args - self.num_required_kw_args
1967 if len(self.args) > 0 and self.args[0].is_self_arg:
1968 min_positional_args -= 1
1969 max_positional_args = len(positional_args)
1970 has_fixed_positional_count = not self.star_arg and \
1971 min_positional_args == max_positional_args
1973 code.globalstate.use_utility_code(raise_double_keywords_utility_code)
1974 code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
1975 if self.num_required_kw_args:
1976 code.globalstate.use_utility_code(raise_keyword_required_utility_code)
1978 if self.starstar_arg or self.star_arg:
1979 self.generate_stararg_init_code(max_positional_args, code)
1981 # --- optimised code when we receive keyword arguments
1982 if self.num_required_kw_args:
1983 likely_hint = "likely"
1984 else:
1985 likely_hint = "unlikely"
1986 code.putln("if (%s(%s)) {" % (likely_hint, Naming.kwds_cname))
1987 self.generate_keyword_unpacking_code(
1988 min_positional_args, max_positional_args,
1989 has_fixed_positional_count,
1990 positional_args, kw_only_args, argtuple_error_label, code)
1992 # --- optimised code when we do not receive any keyword arguments
1993 if (self.num_required_kw_args and min_positional_args > 0) or min_positional_args == max_positional_args:
1994 # Python raises arg tuple related errors first, so we must
1995 # check the length here
1996 if min_positional_args == max_positional_args and not self.star_arg:
1997 compare = '!='
1998 else:
1999 compare = '<'
2000 code.putln('} else if (PyTuple_GET_SIZE(%s) %s %d) {' % (
2001 Naming.args_cname, compare, min_positional_args))
2002 code.put_goto(argtuple_error_label)
2004 if self.num_required_kw_args:
2005 # pure error case: keywords required but not passed
2006 if max_positional_args > min_positional_args and not self.star_arg:
2007 code.putln('} else if (PyTuple_GET_SIZE(%s) > %d) {' % (
2008 Naming.args_cname, max_positional_args))
2009 code.put_goto(argtuple_error_label)
2010 code.putln('} else {')
2011 for i, arg in enumerate(kw_only_args):
2012 if not arg.default:
2013 # required keyword-only argument missing
2014 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
2015 self.name.utf8encode(),
2016 arg.name_entry.pystring_cname))
2017 code.putln(code.error_goto(self.pos))
2018 break
2020 elif min_positional_args == max_positional_args:
2021 # parse the exact number of positional arguments from the
2022 # args tuple
2023 code.putln('} else {')
2024 for i, arg in enumerate(positional_args):
2025 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2026 self.generate_arg_assignment(arg, item, code)
2028 else:
2029 # parse the positional arguments from the variable length
2030 # args tuple
2031 code.putln('} else {')
2032 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2033 if self.star_arg:
2034 code.putln('default:')
2035 reversed_args = list(enumerate(positional_args))[::-1]
2036 for i, arg in reversed_args:
2037 if i >= min_positional_args-1:
2038 if min_positional_args > 1:
2039 code.putln('case %2d:' % (i+1)) # pure code beautification
2040 else:
2041 code.put('case %2d: ' % (i+1))
2042 item = "PyTuple_GET_ITEM(%s, %d)" % (Naming.args_cname, i)
2043 self.generate_arg_assignment(arg, item, code)
2044 if min_positional_args == 0:
2045 code.put('case 0: ')
2046 code.putln('break;')
2047 if self.star_arg:
2048 if min_positional_args:
2049 for i in range(min_positional_args-1, -1, -1):
2050 code.putln('case %2d:' % i)
2051 code.put_goto(argtuple_error_label)
2052 else:
2053 code.put('default: ')
2054 code.put_goto(argtuple_error_label)
2055 code.putln('}')
2057 code.putln('}')
2059 if code.label_used(argtuple_error_label):
2060 code.put_goto(success_label)
2061 code.put_label(argtuple_error_label)
2062 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
2063 self.name.utf8encode(), has_fixed_positional_count,
2064 min_positional_args, max_positional_args,
2065 Naming.args_cname))
2066 code.putln(code.error_goto(self.pos))
2068 def generate_stararg_init_code(self, max_positional_args, code):
2069 if self.starstar_arg:
2070 self.starstar_arg.entry.xdecref_cleanup = 0
2071 code.putln('%s = PyDict_New(); if (unlikely(!%s)) return %s;' % (
2072 self.starstar_arg.entry.cname,
2073 self.starstar_arg.entry.cname,
2074 self.error_value()))
2075 if self.star_arg:
2076 self.star_arg.entry.xdecref_cleanup = 0
2077 code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
2078 Naming.args_cname,
2079 max_positional_args))
2080 code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
2081 self.star_arg.entry.cname, Naming.args_cname,
2082 max_positional_args, Naming.args_cname))
2083 if self.starstar_arg:
2084 code.putln("")
2085 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
2086 code.put_decref(self.starstar_arg.entry.cname, py_object_type)
2087 code.putln('return %s;' % self.error_value())
2088 code.putln('}')
2089 else:
2090 code.putln("if (unlikely(!%s)) return %s;" % (
2091 self.star_arg.entry.cname, self.error_value()))
2092 code.putln('} else {')
2093 code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
2094 code.put_incref(Naming.empty_tuple, py_object_type)
2095 code.putln('}')
2097 def generate_keyword_unpacking_code(self, min_positional_args, max_positional_args,
2098 has_fixed_positional_count, positional_args,
2099 kw_only_args, argtuple_error_label, code):
2100 all_args = tuple(positional_args) + tuple(kw_only_args)
2101 max_args = len(all_args)
2103 code.putln("PyObject* values[%d] = {%s};" % (
2104 max_args, ('0,'*max_args)[:-1]))
2105 code.putln("Py_ssize_t kw_args = PyDict_Size(%s);" %
2106 Naming.kwds_cname)
2108 # parse the tuple and check that it's not too long
2109 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2110 if self.star_arg:
2111 code.putln('default:')
2112 for i in range(max_positional_args-1, -1, -1):
2113 code.put('case %2d: ' % (i+1))
2114 code.putln("values[%d] = PyTuple_GET_ITEM(%s, %d);" % (
2115 i, Naming.args_cname, i))
2116 code.putln('case 0: break;')
2117 if not self.star_arg:
2118 code.put('default: ') # more arguments than allowed
2119 code.put_goto(argtuple_error_label)
2120 code.putln('}')
2122 # now fill up the required arguments with values from the kw dict
2123 last_required_arg = -1
2124 for i, arg in enumerate(all_args):
2125 if not arg.default:
2126 last_required_arg = i
2127 if last_required_arg >= 0:
2128 code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname)
2129 for i, arg in enumerate(all_args[:last_required_arg+1]):
2130 if i <= max_positional_args:
2131 if self.star_arg and i == max_positional_args:
2132 code.putln('default:')
2133 else:
2134 code.putln('case %2d:' % i)
2135 if arg.default:
2136 # handled in ParseOptionalKeywords() below
2137 continue
2138 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
2139 i, Naming.kwds_cname, arg.name_entry.pystring_cname))
2140 if i < min_positional_args:
2141 code.putln('if (likely(values[%d])) kw_args--;' % i);
2142 if i == 0:
2143 # special case: we know arg 0 is missing
2144 code.put('else ')
2145 code.put_goto(argtuple_error_label)
2146 else:
2147 # print the correct number of values (args or
2148 # kwargs) that were passed into positional
2149 # arguments up to this point
2150 code.putln('else {')
2151 code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
2152 self.name.utf8encode(), has_fixed_positional_count,
2153 min_positional_args, max_positional_args, i))
2154 code.putln(code.error_goto(self.pos))
2155 code.putln('}')
2156 else:
2157 code.putln('if (values[%d]) kw_args--;' % i);
2158 if arg.kw_only and not arg.default:
2159 code.putln('else {')
2160 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
2161 self.name.utf8encode(), arg.name_entry.pystring_cname))
2162 code.putln(code.error_goto(self.pos))
2163 code.putln('}')
2164 code.putln('}')
2166 code.putln('if (unlikely(kw_args > 0)) {')
2167 # non-positional kw args left in dict: default args, **kwargs or error
2168 if self.star_arg:
2169 code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % (
2170 Naming.args_cname, max_positional_args,
2171 Naming.args_cname, max_positional_args))
2172 pos_arg_count = "used_pos_args"
2173 else:
2174 pos_arg_count = "PyTuple_GET_SIZE(%s)" % Naming.args_cname
2175 code.globalstate.use_utility_code(parse_keywords_utility_code)
2176 code.put(
2177 'if (unlikely(__Pyx_ParseOptionalKeywords(%s, %s, %s, values, %s, "%s") < 0)) ' % (
2178 Naming.kwds_cname,
2179 Naming.pykwdlist_cname,
2180 self.starstar_arg and self.starstar_arg.entry.cname or '0',
2181 pos_arg_count,
2182 self.name.utf8encode()))
2183 code.putln(code.error_goto(self.pos))
2184 code.putln('}')
2186 # convert arg values to their final type and assign them
2187 for i, arg in enumerate(all_args):
2188 if arg.default:
2189 code.putln("if (values[%d]) {" % i)
2190 self.generate_arg_assignment(arg, "values[%d]" % i, code)
2191 if arg.default:
2192 code.putln('}')
2194 def generate_argument_conversion_code(self, code):
2195 # Generate code to convert arguments from
2196 # signature type to declared type, if needed.
2197 for arg in self.args:
2198 if arg.needs_conversion:
2199 self.generate_arg_conversion(arg, code)
2201 def generate_arg_conversion(self, arg, code):
2202 # Generate conversion code for one argument.
2203 old_type = arg.hdr_type
2204 new_type = arg.type
2205 if old_type.is_pyobject:
2206 if arg.default:
2207 code.putln("if (%s) {" % arg.hdr_cname)
2208 else:
2209 code.putln("assert(%s); {" % arg.hdr_cname)
2210 self.generate_arg_conversion_from_pyobject(arg, code)
2211 code.putln("}")
2212 elif new_type.is_pyobject:
2213 self.generate_arg_conversion_to_pyobject(arg, code)
2214 else:
2215 if new_type.assignable_from(old_type):
2216 code.putln(
2217 "%s = %s;" % (arg.entry.cname, arg.hdr_cname))
2218 else:
2219 error(arg.pos,
2220 "Cannot convert 1 argument from '%s' to '%s'" %
2221 (old_type, new_type))
2223 def generate_arg_conversion_from_pyobject(self, arg, code):
2224 new_type = arg.type
2225 func = new_type.from_py_function
2226 # copied from CoerceFromPyTypeNode
2227 if func:
2228 code.putln("%s = %s(%s); %s" % (
2229 arg.entry.cname,
2230 func,
2231 arg.hdr_cname,
2232 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
2233 else:
2234 error(arg.pos,
2235 "Cannot convert Python object argument to type '%s'"
2236 % new_type)
2238 def generate_arg_conversion_to_pyobject(self, arg, code):
2239 old_type = arg.hdr_type
2240 func = old_type.to_py_function
2241 if func:
2242 code.putln("%s = %s(%s); %s" % (
2243 arg.entry.cname,
2244 func,
2245 arg.hdr_cname,
2246 code.error_goto_if_null(arg.entry.cname, arg.pos)))
2247 else:
2248 error(arg.pos,
2249 "Cannot convert argument of type '%s' to Python object"
2250 % old_type)
2252 def generate_argument_type_tests(self, code):
2253 # Generate type tests for args whose signature
2254 # type is PyObject * and whose declared type is
2255 # a subtype thereof.
2256 for arg in self.args:
2257 if arg.needs_type_test:
2258 self.generate_arg_type_test(arg, code)
2260 def generate_arg_type_test(self, arg, code):
2261 # Generate type test for one argument.
2262 if arg.type.typeobj_is_available():
2263 typeptr_cname = arg.type.typeptr_cname
2264 arg_code = "((PyObject *)%s)" % arg.entry.cname
2265 code.putln(
2266 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
2267 arg_code,
2268 typeptr_cname,
2269 not arg.not_none,
2270 arg.name,
2271 arg.type.is_builtin_type,
2272 code.error_goto(arg.pos)))
2273 else:
2274 error(arg.pos, "Cannot test type of extern C class "
2275 "without type object name specification")
2277 def error_value(self):
2278 return self.entry.signature.error_value
2280 def caller_will_check_exceptions(self):
2281 return 1
2283 class OverrideCheckNode(StatNode):
2284 # A Node for dispatching to the def method if it
2285 # is overriden.
2286 #
2287 # py_func
2288 #
2289 # args
2290 # func_temp
2291 # body
2293 child_attrs = ['body']
2295 body = None
2297 def analyse_expressions(self, env):
2298 self.args = env.arg_entries
2299 if self.py_func.is_module_scope:
2300 first_arg = 0
2301 else:
2302 first_arg = 1
2303 import ExprNodes
2304 self.func_node = ExprNodes.PyTempNode(self.pos, env)
2305 call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2306 call_node = ExprNodes.SimpleCallNode(self.pos,
2307 function=self.func_node,
2308 args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
2309 self.body = ReturnStatNode(self.pos, value=call_node)
2310 self.body.analyse_expressions(env)
2312 def generate_execution_code(self, code):
2313 # Check to see if we are an extension type
2314 if self.py_func.is_module_scope:
2315 self_arg = "((PyObject *)%s)" % Naming.module_cname
2316 else:
2317 self_arg = "((PyObject *)%s)" % self.args[0].cname
2318 code.putln("/* Check if called by wrapper */")
2319 code.putln("if (unlikely(%s)) ;" % Naming.skip_dispatch_cname)
2320 code.putln("/* Check if overriden in Python */")
2321 if self.py_func.is_module_scope:
2322 code.putln("else {")
2323 else:
2324 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
2325 err = code.error_goto_if_null(self.func_node.result(), self.pos)
2326 # need to get attribute manually--scope would return cdef method
2327 code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
2328 # It appears that this type is not anywhere exposed in the Python/C API
2329 is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result()
2330 is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
2331 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
2332 self.body.generate_execution_code(code)
2333 code.putln('}')
2334 code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
2335 code.putln("}")
2337 class ClassDefNode(StatNode, BlockNode):
2338 pass
2340 class PyClassDefNode(ClassDefNode):
2341 # A Python class definition.
2342 #
2343 # name EncodedString Name of the class
2344 # doc string or None
2345 # body StatNode Attribute definition code
2346 # entry Symtab.Entry
2347 # scope PyClassScope
2348 #
2349 # The following subnodes are constructed internally:
2350 #
2351 # dict DictNode Class dictionary
2352 # classobj ClassNode Class object
2353 # target NameNode Variable to assign class object to
2355 child_attrs = ["body", "dict", "classobj", "target"]
2357 def __init__(self, pos, name, bases, doc, body):
2358 StatNode.__init__(self, pos)
2359 self.name = name
2360 self.doc = doc
2361 self.body = body
2362 import ExprNodes
2363 self.dict = ExprNodes.DictNode(pos, key_value_pairs = [])
2364 if self.doc and Options.docstrings:
2365 doc = embed_position(self.pos, self.doc)
2366 doc_node = ExprNodes.StringNode(pos, value = doc)
2367 else:
2368 doc_node = None
2369 self.classobj = ExprNodes.ClassNode(pos, name = name,
2370 bases = bases, dict = self.dict, doc = doc_node)
2371 self.target = ExprNodes.NameNode(pos, name = name)
2373 def as_cclass(self):
2374 """
2375 Return this node as if it were declared as an extension class
2376 """
2377 bases = self.classobj.bases.args
2378 if len(bases) == 0:
2379 base_class_name = None
2380 base_class_module = None
2381 elif len(bases) == 1:
2382 base = bases[0]
2383 path = []
2384 from ExprNodes import AttributeNode, NameNode
2385 while isinstance(base, AttributeNode):
2386 path.insert(0, base.attribute)
2387 base = base.obj
2388 if isinstance(base, NameNode):
2389 path.insert(0, base.name)
2390 base_class_name = path[-1]
2391 if len(path) > 1:
2392 base_class_module = u'.'.join(path[:-1])
2393 else:
2394 base_class_module = None
2395 else:
2396 error(self.classobj.bases.args.pos, "Invalid base class")
2397 else:
2398 error(self.classobj.bases.args.pos, "C class may only have one base class")
2399 return None
2401 return CClassDefNode(self.pos,
2402 visibility = 'private',
2403 module_name = None,
2404 class_name = self.name,
2405 base_class_module = base_class_module,
2406 base_class_name = base_class_name,
2407 body = self.body,
2408 in_pxd = False,
2409 doc = self.doc)
2411 def create_scope(self, env):
2412 genv = env
2413 while env.is_py_class_scope or env.is_c_class_scope:
2414 env = env.outer_scope
2415 cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
2416 return cenv
2418 def analyse_declarations(self, env):
2419 self.target.analyse_target_declaration(env)
2420 cenv = self.create_scope(env)
2421 cenv.class_obj_cname = self.target.entry.cname
2422 self.body.analyse_declarations(cenv)
2424 def analyse_expressions(self, env):
2425 self.dict.analyse_expressions(env)
2426 self.classobj.analyse_expressions(env)
2427 genv = env.global_scope()
2428 cenv = self.scope
2429 cenv.class_dict_cname = self.dict.result()
2430 cenv.namespace_cname = cenv.class_obj_cname = self.classobj.result()
2431 self.body.analyse_expressions(cenv)
2432 self.target.analyse_target_expression(env, self.classobj)
2433 self.dict.release_temp(env)
2434 #self.classobj.release_temp(env)
2435 #self.target.release_target_temp(env)
2437 def generate_function_definitions(self, env, code):
2438 self.generate_py_string_decls(self.scope, code)
2439 self.body.generate_function_definitions(self.scope, code)
2441 def generate_execution_code(self, code):
2442 self.dict.generate_evaluation_code(code)
2443 self.classobj.generate_evaluation_code(code)
2444 self.body.generate_execution_code(code)
2445 self.target.generate_assignment_code(self.classobj, code)
2446 self.dict.generate_disposal_code(code)
2449 class CClassDefNode(ClassDefNode):
2450 # An extension type definition.
2451 #
2452 # visibility 'private' or 'public' or 'extern'
2453 # typedef_flag boolean
2454 # api boolean
2455 # module_name string or None For import of extern type objects
2456 # class_name string Unqualified name of class
2457 # as_name string or None Name to declare as in this scope
2458 # base_class_module string or None Module containing the base class
2459 # base_class_name string or None Name of the base class
2460 # objstruct_name string or None Specified C name of object struct
2461 # typeobj_name string or None Specified C name of type object
2462 # in_pxd boolean Is in a .pxd file
2463 # doc string or None
2464 # body StatNode or None
2465 # entry Symtab.Entry
2466 # base_type PyExtensionType or None
2467 # buffer_defaults_node DictNode or None Declares defaults for a buffer
2468 # buffer_defaults_pos
2470 child_attrs = ["body"]
2471 buffer_defaults_node = None
2472 buffer_defaults_pos = None
2473 typedef_flag = False
2474 api = False
2475 objstruct_name = None
2476 typeobj_name = None
2478 def analyse_declarations(self, env):
2479 #print "CClassDefNode.analyse_declarations:", self.class_name
2480 #print "...visibility =", self.visibility
2481 #print "...module_name =", self.module_name
2483 import Buffer
2484 if self.buffer_defaults_node:
2485 buffer_defaults = Buffer.analyse_buffer_options(self.buffer_defaults_pos,
2486 env, [], self.buffer_defaults_node,
2487 need_complete=False)
2488 else:
2489 buffer_defaults = None
2491 if env.in_cinclude and not self.objstruct_name:
2492 error(self.pos, "Object struct name specification required for "
2493 "C class defined in 'extern from' block")
2494 self.base_type = None
2495 # Now that module imports are cached, we need to
2496 # import the modules for extern classes.
2497 if self.module_name:
2498 self.module = None
2499 for module in env.cimported_modules:
2500 if module.name == self.module_name:
2501 self.module = module
2502 if self.module is None:
2503 self.module = ModuleScope(self.module_name, None, env.context)
2504 self.module.has_extern_class = 1
2505 env.cimported_modules.append(self.module)
2507 if self.base_class_name:
2508 if self.base_class_module:
2509 base_class_scope = env.find_module(self.base_class_module, self.pos)
2510 else:
2511 base_class_scope = env
2512 if base_class_scope:
2513 base_class_entry = base_class_scope.find(self.base_class_name, self.pos)
2514 if base_class_entry:
2515 if not base_class_entry.is_type:
2516 error(self.pos, "'%s' is not a type name" % self.base_class_name)
2517 elif not base_class_entry.type.is_extension_type:
2518 error(self.pos, "'%s' is not an extension type" % self.base_class_name)
2519 elif not base_class_entry.type.is_complete():
2520 error(self.pos, "Base class '%s' is incomplete" % self.base_class_name)
2521 else:
2522 self.base_type = base_class_entry.type
2523 has_body = self.body is not None
2524 if self.module_name and self.visibility != 'extern':
2525 module_path = self.module_name.split(".")
2526 home_scope = env.find_imported_module(module_path, self.pos)
2527 if not home_scope:
2528 return
2529 else:
2530 home_scope = env
2531 self.entry = home_scope.declare_c_class(
2532 name = self.class_name,
2533 pos = self.pos,
2534 defining = has_body and self.in_pxd,
2535 implementing = has_body and not self.in_pxd,
2536 module_name = self.module_name,
2537 base_type = self.base_type,
2538 objstruct_cname = self.objstruct_name,
2539 typeobj_cname = self.typeobj_name,
2540 visibility = self.visibility,
2541 typedef_flag = self.typedef_flag,
2542 api = self.api,
2543 buffer_defaults = buffer_defaults)
2544 if home_scope is not env and self.visibility == 'extern':
2545 env.add_imported_entry(self.class_name, self.entry, pos)
2546 scope = self.entry.type.scope
2548 if self.doc and Options.docstrings:
2549 scope.doc = embed_position(self.pos, self.doc)
2551 if has_body:
2552 self.body.analyse_declarations(scope)
2553 if self.in_pxd:
2554 scope.defined = 1
2555 else:
2556 scope.implemented = 1
2557 env.allocate_vtable_names(self.entry)
2559 def analyse_expressions(self, env):
2560 if self.body:
2561 scope = self.entry.type.scope
2562 self.body.analyse_expressions(scope)
2564 def generate_function_definitions(self, env, code):
2565 self.generate_py_string_decls(self.entry.type.scope, code)
2566 if self.body:
2567 self.body.generate_function_definitions(
2568 self.entry.type.scope, code)
2570 def generate_execution_code(self, code):
2571 # This is needed to generate evaluation code for
2572 # default values of method arguments.
2573 if self.body:
2574 self.body.generate_execution_code(code)
2576 def annotate(self, code):
2577 if self.body:
2578 self.body.annotate(code)
2581 class PropertyNode(StatNode):
2582 # Definition of a property in an extension type.
2583 #
2584 # name string
2585 # doc EncodedString or None Doc string
2586 # body StatListNode
2588 child_attrs = ["body"]
2590 def analyse_declarations(self, env):
2591 entry = env.declare_property(self.name, self.doc, self.pos)
2592 if entry:
2593 if self.doc and Options.docstrings:
2594 doc_entry = env.get_string_const(
2595 self.doc, identifier = False)
2596 entry.doc_cname = doc_entry.cname
2597 self.body.analyse_declarations(entry.scope)
2599 def analyse_expressions(self, env):
2600 self.body.analyse_expressions(env)
2602 def generate_function_definitions(self, env, code):
2603 self.body.generate_function_definitions(env, code)
2605 def generate_execution_code(self, code):
2606 pass
2608 def annotate(self, code):
2609 self.body.annotate(code)
2612 class GlobalNode(StatNode):
2613 # Global variable declaration.
2614 #
2615 # names [string]
2617 child_attrs = []
2619 def analyse_declarations(self, env):
2620 for name in self.names:
2621 env.declare_global(name, self.pos)
2623 def analyse_expressions(self, env):
2624 pass
2626 def generate_execution_code(self, code):
2627 pass
2630 class ExprStatNode(StatNode):
2631 # Expression used as a statement.
2632 #
2633 # expr ExprNode
2635 child_attrs = ["expr"]
2637 def analyse_declarations(self, env):
2638 import ExprNodes
2639 if isinstance(self.expr, ExprNodes.GeneralCallNode):
2640 func = self.expr.function.as_cython_attribute()
2641 if func == u'declare':
2642 args, kwds = self.expr.explicit_args_kwds()
2643 if len(args):
2644 error(self.expr.pos, "Variable names must be specified.")
2645 for var, type_node in kwds.key_value_pairs:
2646 type = type_node.analyse_as_type(env)
2647 if type is None:
2648 error(type_node.pos, "Unknown type")
2649 else:
2650 env.declare_var(var.value, type, var.pos, is_cdef = True)
2651 self.__class__ = PassStatNode
2653 def analyse_expressions(self, env):
2654 self.expr.analyse_expressions(env)
2655 self.expr.release_temp(env)
2657 def generate_execution_code(self, code):
2658 self.expr.generate_evaluation_code(code)
2659 if not self.expr.is_temp and self.expr.result():
2660 code.putln("%s;" % self.expr.result())
2661 self.expr.generate_disposal_code(code)
2663 def annotate(self, code):
2664 self.expr.annotate(code)
2667 class AssignmentNode(StatNode):
2668 # Abstract base class for assignment nodes.
2669 #
2670 # The analyse_expressions and generate_execution_code
2671 # phases of assignments are split into two sub-phases
2672 # each, to enable all the right hand sides of a
2673 # parallel assignment to be evaluated before assigning
2674 # to any of the left hand sides.
2676 def analyse_expressions(self, env):
2677 self.analyse_types(env)
2678 self.allocate_rhs_temps(env)
2679 self.allocate_lhs_temps(env)
2681 # def analyse_expressions(self, env):
2682 # self.analyse_expressions_1(env)
2683 # self.analyse_expressions_2(env)
2685 def generate_execution_code(self, code):
2686 self.generate_rhs_evaluation_code(code)
2687 self.generate_assignment_code(code)
2690 class SingleAssignmentNode(AssignmentNode):
2691 # The simplest case:
2692 #
2693 # a = b
2694 #
2695 # lhs ExprNode Left hand side
2696 # rhs ExprNode Right hand side
2697 # first bool Is this guaranteed the first assignment to lhs?
2699 child_attrs = ["lhs", "rhs"]
2700 first = False
2701 declaration_only = False
2703 def analyse_declarations(self, env):
2704 import ExprNodes
2706 # handle declarations of the form x = cython.foo()
2707 if isinstance(self.rhs, ExprNodes.CallNode):
2708 func_name = self.rhs.function.as_cython_attribute()
2709 if func_name:
2710 args, kwds = self.rhs.explicit_args_kwds()
2712 if func_name in ['declare', 'typedef']:
2713 if len(args) > 2 or kwds is not None:
2714 error(rhs.pos, "Can only declare one type at a time.")
2715 return
2716 type = args[0].analyse_as_type(env)
2717 if type is None:
2718 error(args[0].pos, "Unknown type")
2719 return
2720 lhs = self.lhs
2721 if func_name == 'declare':
2722 if isinstance(lhs, ExprNodes.NameNode):
2723 vars = [(lhs.name, lhs.pos)]
2724 elif isinstance(lhs, ExprNodes.TupleNode):
2725 vars = [(var.name, var.pos) for var in lhs.args]
2726 else:
2727 error(lhs.pos, "Invalid declaration")
2728 return
2729 for var, pos in vars:
2730 env.declare_var(var, type, pos, is_cdef = True)
2731 if len(args) == 2:
2732 # we have a value
2733 self.rhs = args[1]
2734 else:
2735 self.declaration_only = True
2736 else:
2737 self.declaration_only = True
2738 if not isinstance(lhs, ExprNodes.NameNode):
2739 error(lhs.pos, "Invalid declaration.")
2740 env.declare_typedef(lhs.name, type, self.pos, visibility='private')
2742 elif func_name in ['struct', 'union']:
2743 self.declaration_only = True
2744 if len(args) > 0 or kwds is None:
2745 error(rhs.pos, "Struct or union members must be given by name.")
2746 return
2747 members = []
2748 for member, type_node in kwds.key_value_pairs:
2749 type = type_node.analyse_as_type(env)
2750 if type is None:
2751 error(type_node.pos, "Unknown type")
2752 else:
2753 members.append((member.value, type, member.pos))
2754 if len(members) < len(kwds.key_value_pairs):
2755 return
2756 if not isinstance(self.lhs, ExprNodes.NameNode):
2757 error(self.lhs.pos, "Invalid declaration.")
2758 name = self.lhs.name
2759 scope = StructOrUnionScope(name)
2760 env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
2761 for member, type, pos in members:
2762 scope.declare_var(member, type, pos)
2764 if self.declaration_only:
2765 return
2766 else:
2767 self.lhs.analyse_target_declaration(env)
2769 def analyse_types(self, env, use_temp = 0):
2770 self.rhs.analyse_types(env)
2771 self.lhs.analyse_target_types(env)
2772 self.lhs.gil_assignment_check(env)
2773 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2774 if use_temp:
2775 self.rhs = self.rhs.coerce_to_temp(env)
2777 def allocate_rhs_temps(self, env):
2778 self.rhs.allocate_temps(env)
2780 def allocate_lhs_temps(self, env):
2781 self.lhs.allocate_target_temps(env, self.rhs)
2782 #self.lhs.release_target_temp(env)
2783 #self.rhs.release_temp(env)
2785 # def analyse_expressions_1(self, env, use_temp = 0):
2786 # self.rhs.analyse_types(env)
2787 # self.lhs.analyse_target_types(env)
2788 # self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2789 # if use_temp:
2790 # self.rhs = self.rhs.coerce_to_temp(env)
2791 # self.rhs.allocate_temps(env)
2792 #
2793 # def analyse_expressions_2(self, env):
2794 # self.lhs.allocate_target_temps(env)
2795 # self.lhs.release_target_temp(env)
2796 # self.rhs.release_temp(env)
2798 def generate_rhs_evaluation_code(self, code):
2799 self.rhs.generate_evaluation_code(code)
2801 def generate_assignment_code(self, code):
2802 self.lhs.generate_assignment_code(self.rhs, code)
2804 def annotate(self, code):
2805 self.lhs.annotate(code)
2806 self.rhs.annotate(code)
2809 class CascadedAssignmentNode(AssignmentNode):
2810 # An assignment with multiple left hand sides:
2811 #
2812 # a = b = c
2813 #
2814 # lhs_list [ExprNode] Left hand sides
2815 # rhs ExprNode Right hand sides
2816 #
2817 # Used internally:
2818 #
2819 # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
2821 child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
2822 coerced_rhs_list = None
2824 def analyse_declarations(self, env):
2825 for lhs in self.lhs_list:
2826 lhs.analyse_target_declaration(env)
2828 def analyse_types(self, env, use_temp = 0):
2829 self.rhs.analyse_types(env)
2830 if use_temp:
2831 self.rhs = self.rhs.coerce_to_temp(env)
2832 else:
2833 self.rhs = self.rhs.coerce_to_simple(env)
2834 from ExprNodes import CloneNode
2835 self.coerced_rhs_list = []
2836 for lhs in self.lhs_list:
2837 lhs.analyse_target_types(env)
2838 lhs.gil_assignment_check(env)
2839 rhs = CloneNode(self.rhs)
2840 rhs = rhs.coerce_to(lhs.type, env)
2841 self.coerced_rhs_list.append(rhs)
2843 def allocate_rhs_temps(self, env):
2844 self.rhs.allocate_temps(env)
2846 def allocate_lhs_temps(self, env):
2847 for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
2848 rhs.allocate_temps(env)
2849 lhs.allocate_target_temps(env, rhs)
2850 #lhs.release_target_temp(env)
2851 #rhs.release_temp(env)
2852 self.rhs.release_temp(env)
2854 # def analyse_expressions_1(self, env, use_temp = 0):
2855 # self.rhs.analyse_types(env)
2856 # if use_temp:
2857 # self.rhs = self.rhs.coerce_to_temp(env)
2858 # else:
2859 # self.rhs = self.rhs.coerce_to_simple(env)
2860 # self.rhs.allocate_temps(env)
2861 #
2862 # def analyse_expressions_2(self, env):
2863 # from ExprNodes import CloneNode
2864 # self.coerced_rhs_list = []
2865 # for lhs in self.lhs_list:
2866 # lhs.analyse_target_types(env)
2867 # rhs = CloneNode(self.rhs)
2868 # rhs = rhs.coerce_to(lhs.type, env)
2869 # self.coerced_rhs_list.append(rhs)
2870 # rhs.allocate_temps(env)
2871 # lhs.allocate_target_temps(env)
2872 # lhs.release_target_temp(env)
2873 # rhs.release_temp(env)
2874 # self.rhs.release_temp(env)
2876 def generate_rhs_evaluation_code(self, code):
2877 self.rhs.generate_evaluation_code(code)
2879 def generate_assignment_code(self, code):
2880 for i in range(len(self.lhs_list)):
2881 lhs = self.lhs_list[i]
2882 rhs = self.coerced_rhs_list[i]
2883 rhs.generate_evaluation_code(code)
2884 lhs.generate_assignment_code(rhs, code)
2885 # Assignment has disposed of the cloned RHS
2886 self.rhs.generate_disposal_code(code)
2888 def annotate(self, code):
2889 for i in range(len(self.lhs_list)):
2890 lhs = self.lhs_list[i].annotate(code)
2891 rhs = self.coerced_rhs_list[i].annotate(code)
2892 self.rhs.annotate(code)
2895 class ParallelAssignmentNode(AssignmentNode):
2896 # A combined packing/unpacking assignment:
2897 #
2898 # a, b, c = d, e, f
2899 #
2900 # This has been rearranged by the parser into
2901 #
2902 # a = d ; b = e ; c = f
2903 #
2904 # but we must evaluate all the right hand sides
2905 # before assigning to any of the left hand sides.
2906 #
2907 # stats [AssignmentNode] The constituent assignments
2909 child_attrs = ["stats"]
2911 def analyse_declarations(self, env):
2912 for stat in self.stats:
2913 stat.analyse_declarations(env)
2915 def analyse_expressions(self, env):
2916 for stat in self.stats:
2917 stat.analyse_types(env, use_temp = 1)
2918 stat.allocate_rhs_temps(env)
2919 for stat in self.stats:
2920 stat.allocate_lhs_temps(env)
2922 # def analyse_expressions(self, env):
2923 # for stat in self.stats:
2924 # stat.analyse_expressions_1(env, use_temp = 1)
2925 # for stat in self.stats:
2926 # stat.analyse_expressions_2(env)
2928 def generate_execution_code(self, code):
2929 for stat in self.stats:
2930 stat.generate_rhs_evaluation_code(code)
2931 for stat in self.stats:
2932 stat.generate_assignment_code(code)
2934 def annotate(self, code):
2935 for stat in self.stats:
2936 stat.annotate(code)
2939 class InPlaceAssignmentNode(AssignmentNode):
2940 # An in place arithmatic operand:
2941 #
2942 # a += b
2943 # a -= b
2944 # ...
2945 #
2946 # lhs ExprNode Left hand side
2947 # rhs ExprNode Right hand side
2948 # op char one of "+-*/%^&|"
2949 # dup (ExprNode) copy of lhs used for operation (auto-generated)
2950 #
2951 # This code is a bit tricky because in order to obey Python
2952 # semantics the sub-expressions (e.g. indices) of the lhs must
2953 # not be evaluated twice. So we must re-use the values calculated
2954 # in evaluation phase for the assignment phase as well.
2955 # Fortunately, the type of the lhs node is fairly constrained
2956 # (it must be a NameNode, AttributeNode, or IndexNode).
2958 child_attrs = ["lhs", "rhs"]
2959 dup = None
2961 def analyse_declarations(self, env):
2962 self.lhs.analyse_target_declaration(env)
2964 def analyse_types(self, env):
2965 self.dup = self.create_dup_node(env) # re-assigns lhs to a shallow copy
2966 self.rhs.analyse_types(env)
2967 self.lhs.analyse_target_types(env)
2968 if Options.incref_local_binop and self.dup.type.is_pyobject:
2969 self.dup = self.dup.coerce_to_temp(env)
2971 def allocate_rhs_temps(self, env):
2972 import ExprNodes
2973 if self.lhs.type.is_pyobject:
2974 self.rhs = self.rhs.coerce_to_pyobject(env)
2975 elif self.rhs.type.is_pyobject:
2976 self.rhs = self.rhs.coerce_to(self.lhs.type, env)
2977 if self.lhs.type.is_pyobject:
2978 self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
2979 self.result_value.allocate_temps(env)
2980 # if use_temp:
2981 # self.rhs = self.rhs.coerce_to_temp(env)
2982 self.rhs.allocate_temps(env)
2983 self.dup.allocate_subexpr_temps(env)
2984 self.dup.allocate_temp(env)
2986 def allocate_lhs_temps(self, env):
2987 self.lhs.allocate_target_temps(env, self.rhs)
2988 # self.lhs.release_target_temp(env)
2989 self.dup.release_temp(env)
2990 if self.dup.is_temp:
2991 self.dup.release_subexpr_temps(env)
2992 # self.rhs.release_temp(env)
2993 if self.lhs.type.is_pyobject:
2994 self.result_value.release_temp(env)
2996 def generate_execution_code(self, code):
2997 self.rhs.generate_evaluation_code(code)
2998 self.dup.generate_subexpr_evaluation_code(code)
2999 # self.dup.generate_result_code is run only if it is not buffer access
3000 if self.operator == "**":
3001 extra = ", Py_None"
3002 else:
3003 extra = ""
3004 import ExprNodes
3005 if self.lhs.type.is_pyobject:
3006 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3007 error(self.pos, "In-place operators not allowed on object buffers in this release.")
3008 self.dup.generate_result_code(code)
3009 code.putln(
3010 "%s = %s(%s, %s%s); %s" % (
3011 self.result_value.result(),
3012 self.py_operation_function(),
3013 self.dup.py_result(),
3014 self.rhs.py_result(),
3015 extra,
3016 code.error_goto_if_null(self.result_value.py_result(), self.pos)))
3017 self.result_value.generate_evaluation_code(code) # May be a type check...
3018 self.rhs.generate_disposal_code(code)
3019 self.dup.generate_disposal_code(code)
3020 self.lhs.generate_assignment_code(self.result_value, code)
3021 else:
3022 c_op = self.operator
3023 if c_op == "//":
3024 c_op = "/"
3025 elif c_op == "**":
3026 if self.lhs.type.is_int and self.rhs.type.is_int:
3027 error(self.pos, "** with two C int types is ambiguous")
3028 else:
3029 error(self.pos, "No C inplace power operator")
3030 # have to do assignment directly to avoid side-effects
3031 if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
3032 self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
3033 else:
3034 self.dup.generate_result_code(code)
3035 code.putln("%s %s= %s;" % (self.lhs.result(), c_op, self.rhs.result()) )
3036 self.rhs.generate_disposal_code(code)
3037 if self.dup.is_temp:
3038 self.dup.generate_subexpr_disposal_code(code)
3040 def create_dup_node(self, env):
3041 import ExprNodes
3042 self.dup = self.lhs
3043 self.dup.analyse_types(env)
3044 if isinstance(self.lhs, ExprNodes.NameNode):
3045 target_lhs = ExprNodes.NameNode(self.dup.pos,
3046 name = self.dup.name,
3047 is_temp = self.dup.is_temp,
3048 entry = self.dup.entry)
3049 elif isinstance(self.lhs, ExprNodes.AttributeNode):
3050 target_lhs = ExprNodes.AttributeNode(self.dup.pos,
3051 obj = ExprNodes.CloneNode(self.lhs.obj),
3052 attribute = self.dup.attribute,
3053 is_temp = self.dup.is_temp)
3054 elif isinstance(self.lhs, ExprNodes.IndexNode):
3055 if self.lhs.index:
3056 index = ExprNodes.CloneNode(self.lhs.index)
3057 else:
3058 index = None
3059 if self.lhs.indices:
3060 indices = [ExprNodes.CloneNode(x) for x in self.lhs.indices]
3061 else:
3062 indices = []
3063 target_lhs = ExprNodes.IndexNode(self.dup.pos,
3064 base = ExprNodes.CloneNode(self.dup.base),
3065 index = index,
3066 indices = indices,
3067 is_temp = self.dup.is_temp)
3068 self.lhs = target_lhs
3069 return self.dup
3071 def py_operation_function(self):
3072 return self.py_functions[self.operator]
3074 py_functions = {
3075 "|": "PyNumber_InPlaceOr",
3076 "^": "PyNumber_InPlaceXor",
3077 "&": "PyNumber_InPlaceAnd",
3078 "+": "PyNumber_InPlaceAdd",
3079 "-": "PyNumber_InPlaceSubtract",
3080 "*": "PyNumber_InPlaceMultiply",
3081 "/": "PyNumber_InPlaceDivide",
3082 "%": "PyNumber_InPlaceRemainder",
3083 "<<": "PyNumber_InPlaceLshift",
3084 ">>": "PyNumber_InPlaceRshift",
3085 "**": "PyNumber_InPlacePower",
3086 "//": "PyNumber_InPlaceFloorDivide",
3087 }
3089 def annotate(self, code):
3090 self.lhs.annotate(code)
3091 self.rhs.annotate(code)
3092 self.dup.annotate(code)
3095 class PrintStatNode(StatNode):
3096 # print statement
3097 #
3098 # arg_tuple TupleNode
3099 # append_newline boolean
3101 child_attrs = ["arg_tuple"]
3103 def analyse_expressions(self, env):
3104 self.arg_tuple.analyse_expressions(env)
3105 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
3106 self.arg_tuple.release_temp(env)
3107 env.use_utility_code(printing_utility_code)
3108 self.gil_check(env)
3110 gil_message = "Python print statement"
3112 def generate_execution_code(self, code):
3113 self.arg_tuple.generate_evaluation_code(code)
3114 code.putln(
3115 "if (__Pyx_Print(%s, %d) < 0) %s" % (
3116 self.arg_tuple.py_result(),
3117 self.append_newline,
3118 code.error_goto(self.pos)))
3119 self.arg_tuple.generate_disposal_code(code)
3121 def annotate(self, code):
3122 self.arg_tuple.annotate(code)
3125 class ExecStatNode(StatNode):
3126 # exec statement
3127 #
3128 # args [ExprNode]
3130 child_attrs = ["args"]
3132 def analyse_expressions(self, env):
3133 for i, arg in enumerate(self.args):
3134 arg.analyse_expressions(env)
3135 arg = arg.coerce_to_pyobject(env)
3136 arg.release_temp(env)
3137 self.args[i] = arg
3138 self.temp_result = env.allocate_temp_pyobject()
3139 env.release_temp(self.temp_result)
3140 env.use_utility_code(Builtin.pyexec_utility_code)
3141 self.gil_check(env)
3143 gil_message = "Python exec statement"
3145 def generate_execution_code(self, code):
3146 args = []
3147 for arg in self.args:
3148 arg.generate_evaluation_code(code)
3149 args.append( arg.py_result() )
3150 args = tuple(args + ['0', '0'][:3-len(args)])
3151 code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
3152 (self.temp_result,) + args))
3153 for arg in self.args:
3154 arg.generate_disposal_code(code)
3155 code.putln(
3156 code.error_goto_if_null(self.temp_result, self.pos))
3157 code.put_decref_clear(self.temp_result, py_object_type)
3159 def annotate(self, code):
3160 for arg in self.args:
3161 arg.annotate(code)
3164 class DelStatNode(StatNode):
3165 # del statement
3166 #
3167 # args [ExprNode]
3169 child_attrs = ["args"]
3171 def analyse_declarations(self, env):
3172 for arg in self.args:
3173 arg.analyse_target_declaration(env)
3175 def analyse_expressions(self, env):
3176 for arg in self.args:
3177 arg.analyse_target_expression(env, None)
3178 if arg.type.is_pyobject:
3179 self.gil_check(env)
3180 else:
3181 error(arg.pos, "Deletion of non-Python object")
3182 #arg.release_target_temp(env)
3184 gil_message = "Deleting Python object"
3186 def generate_execution_code(self, code):
3187 for arg in self.args:
3188 if arg.type.is_pyobject:
3189 arg.generate_deletion_code(code)
3190 # else error reported earlier
3192 def annotate(self, code):
3193 for arg in self.args:
3194 arg.annotate(code)
3197 class PassStatNode(StatNode):
3198 # pass statement
3200 child_attrs = []
3202 def analyse_expressions(self, env):
3203 pass
3205 def generate_execution_code(self, code):
3206 pass
3209 class BreakStatNode(StatNode):
3211 child_attrs = []
3213 def analyse_expressions(self, env):
3214 pass
3216 def generate_execution_code(self, code):
3217 if not code.break_label:
3218 error(self.pos, "break statement not inside loop")
3219 else:
3220 #code.putln(
3221 # "goto %s;" %
3222 # code.break_label)
3223 code.put_goto(code.break_label)
3226 class ContinueStatNode(StatNode):
3228 child_attrs = []
3230 def analyse_expressions(self, env):
3231 pass
3233 def generate_execution_code(self, code):
3234 if code.funcstate.in_try_finally:
3235 error(self.pos, "continue statement inside try of try...finally")
3236 elif not code.continue_label:
3237 error(self.pos, "continue statement not inside loop")
3238 else:
3239 code.put_goto(code.continue_label)
3242 class ReturnStatNode(StatNode):
3243 # return statement
3244 #
3245 # value ExprNode or None
3246 # return_type PyrexType
3247 # temps_in_use [Entry] Temps in use at time of return
3249 child_attrs = ["value"]
3251 def analyse_expressions(self, env):
3252 return_type = env.return_type
3253 self.return_type = return_type
3254 self.temps_in_use = env.temps_in_use()
3255 if not return_type:
3256 error(self.pos, "Return not inside a function body")
3257 return
3258 if self.value:
3259 self.value.analyse_types(env)
3260 if return_type.is_void or return_type.is_returncode:
3261 error(self.value.pos,
3262 "Return with value in void function")
3263 else:
3264 self.value = self.value.coerce_to(env.return_type, env)
3265 self.value.allocate_temps(env)
3266 self.value.release_temp(env)
3267 else:
3268 if (not return_type.is_void
3269 and not return_type.is_pyobject
3270 and not return_type.is_returncode):
3271 error(self.pos, "Return value required")
3272 if return_type.is_pyobject:
3273 self.gil_check(env)
3275 gil_message = "Returning Python object"
3277 def generate_execution_code(self, code):
3278 code.mark_pos(self.pos)
3279 if not self.return_type:
3280 # error reported earlier
3281 return
3282 if self.value:
3283 self.value.generate_evaluation_code(code)
3284 self.value.make_owned_reference(code)
3285 code.putln(
3286 "%s = %s;" % (
3287 Naming.retval_cname,
3288 self.value.result_as(self.return_type)))
3289 self.value.generate_post_assignment_code(code)
3290 else:
3291 if self.return_type.is_pyobject:
3292 code.put_init_to_py_none(Naming.retval_cname, self.return_type)
3293 elif self.return_type.is_returncode:
3294 code.putln(
3295 "%s = %s;" % (
3296 Naming.retval_cname,
3297 self.return_type.default_value))
3298 # free temps the old way
3299 for entry in self.temps_in_use:
3300 code.put_var_decref_clear(entry)
3301 # free temps the new way
3302 for cname, type in code.funcstate.temps_holding_reference():
3303 code.put_decref_clear(cname, type)
3304 #code.putln(
3305 # "goto %s;" %
3306 # code.return_label)
3307 code.put_goto(code.return_label)
3309 def annotate(self, code):
3310 if self.value:
3311 self.value.annotate(code)
3314 class RaiseStatNode(StatNode):
3315 # raise statement
3316 #
3317 # exc_type ExprNode or None
3318 # exc_value ExprNode or None
3319 # exc_tb ExprNode or None
3321 child_attrs = ["exc_type", "exc_value", "exc_tb"]
3323 def analyse_expressions(self, env):
3324 if self.exc_type:
3325 self.exc_type.analyse_types(env)
3326 self.exc_type = self.exc_type.coerce_to_pyobject(env)
3327 self.exc_type.allocate_temps(env)
3328 if self.exc_value:
3329 self.exc_value.analyse_types(env)
3330 self.exc_value = self.exc_value.coerce_to_pyobject(env)
3331 self.exc_value.allocate_temps(env)
3332 if self.exc_tb:
3333 self.exc_tb.analyse_types(env)
3334 self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
3335 self.exc_tb.allocate_temps(env)
3336 if self.exc_type:
3337 self.exc_type.release_temp(env)
3338 if self.exc_value:
3339 self.exc_value.release_temp(env)
3340 if self.exc_tb:
3341 self.exc_tb.release_temp(env)
3342 env.use_utility_code(raise_utility_code)
3343 env.use_utility_code(restore_exception_utility_code)
3344 self.gil_check(env)
3346 gil_message = "Raising exception"
3348 def generate_execution_code(self, code):
3349 if self.exc_type:
3350 self.exc_type.generate_evaluation_code(code)
3351 type_code = self.exc_type.py_result()
3352 else:
3353 type_code = 0
3354 if self.exc_value:
3355 self.exc_value.generate_evaluation_code(code)
3356 value_code = self.exc_value.py_result()
3357 else:
3358 value_code = "0"
3359 if self.exc_tb:
3360 self.exc_tb.generate_evaluation_code(code)
3361 tb_code = self.exc_tb.py_result()
3362 else:
3363 tb_code = "0"
3364 if self.exc_type or self.exc_value or self.exc_tb:
3365 code.putln(
3366 "__Pyx_Raise(%s, %s, %s);" % (
3367 type_code,
3368 value_code,
3369 tb_code))
3370 else:
3371 code.putln(
3372 "__Pyx_ReRaise();")
3373 if self.exc_type:
3374 self.exc_type.generate_disposal_code(code)
3375 if self.exc_value:
3376 self.exc_value.generate_disposal_code(code)
3377 if self.exc_tb:
3378 self.exc_tb.generate_disposal_code(code)
3379 code.putln(
3380 code.error_goto(self.pos))
3382 def annotate(self, code):
3383 if self.exc_type:
3384 self.exc_type.annotate(code)
3385 if self.exc_value:
3386 self.exc_value.annotate(code)
3387 if self.exc_tb:
3388 self.exc_tb.annotate(code)
3391 class ReraiseStatNode(StatNode):
3393 child_attrs = []
3395 def analyse_expressions(self, env):
3396 self.gil_check(env)
3397 env.use_utility_code(raise_utility_code)
3398 env.use_utility_code(restore_exception_utility_code)
3400 gil_message = "Raising exception"
3402 def generate_execution_code(self, code):
3403 vars = code.funcstate.exc_vars
3404 if vars:
3405 code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars))
3406 code.putln(code.error_goto(self.pos))
3407 else:
3408 error(self.pos, "Reraise not inside except clause")
3411 class AssertStatNode(StatNode):
3412 # assert statement
3413 #
3414 # cond ExprNode
3415 # value ExprNode or None
3417 child_attrs = ["cond", "value"]
3419 def analyse_expressions(self, env):
3420 self.cond = self.cond.analyse_boolean_expression(env)
3421 if self.value:
3422 self.value.analyse_types(env)
3423 self.value = self.value.coerce_to_pyobject(env)
3424 self.value.allocate_temps(env)
3425 self.cond.release_temp(env)
3426 if self.value:
3427 self.value.release_temp(env)
3428 self.gil_check(env)
3429 #env.recycle_pending_temps() # TEMPORARY
3431 gil_message = "Raising exception"
3433 def generate_execution_code(self, code):
3434 code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
3435 self.cond.generate_evaluation_code(code)
3436 code.putln(
3437 "if (unlikely(!%s)) {" %
3438 self.cond.result())
3439 if self.value:
3440 self.value.generate_evaluation_code(code)
3441 code.putln(
3442 "PyErr_SetObject(PyExc_AssertionError, %s);" %
3443 self.value.py_result())
3444 self.value.generate_disposal_code(code)
3445 else:
3446 code.putln(
3447 "PyErr_SetNone(PyExc_AssertionError);")
3448 code.putln(
3449 code.error_goto(self.pos))
3450 code.putln(
3451 "}")
3452 self.cond.generate_disposal_code(code)
3453 code.putln("#endif")
3455 def annotate(self, code):
3456 self.cond.annotate(code)
3457 if self.value:
3458 self.value.annotate(code)
3461 class IfStatNode(StatNode):
3462 # if statement
3463 #
3464 # if_clauses [IfClauseNode]
3465 # else_clause StatNode or None
3467 child_attrs = ["if_clauses", "else_clause"]
3469 def analyse_control_flow(self, env):
3470 env.start_branching(self.pos)
3471 for if_clause in self.if_clauses:
3472 if_clause.analyse_control_flow(env)
3473 env.next_branch(if_clause.end_pos())
3474 if self.else_clause:
3475 self.else_clause.analyse_control_flow(env)
3476 env.finish_branching(self.end_pos())
3478 def analyse_declarations(self, env):
3479 for if_clause in self.if_clauses:
3480 if_clause.analyse_declarations(env)
3481 if self.else_clause:
3482 self.else_clause.analyse_declarations(env)
3484 def analyse_expressions(self, env):
3485 for if_clause in self.if_clauses:
3486 if_clause.analyse_expressions(env)
3487 if self.else_clause:
3488 self.else_clause.analyse_expressions(env)
3490 def generate_execution_code(self, code):
3491 code.mark_pos(self.pos)
3492 end_label = code.new_label()
3493 for if_clause in self.if_clauses:
3494 if_clause.generate_execution_code(code, end_label)
3495 if self.else_clause:
3496 code.putln("/*else*/ {")
3497 self.else_clause.generate_execution_code(code)
3498 code.putln("}")
3499 code.put_label(end_label)
3501 def annotate(self, code):
3502 for if_clause in self.if_clauses:
3503 if_clause.annotate(code)
3504 if self.else_clause:
3505 self.else_clause.annotate(code)
3508 class IfClauseNode(Node):
3509 # if or elif clause in an if statement
3510 #
3511 # condition ExprNode
3512 # body StatNode
3514 child_attrs = ["condition", "body"]
3516 def analyse_control_flow(self, env):
3517 self.body.analyse_control_flow(env)
3519 def analyse_declarations(self, env):
3520 self.condition.analyse_declarations(env)
3521 self.body.analyse_declarations(env)
3523 def analyse_expressions(self, env):
3524 self.condition = \
3525 self.condition.analyse_temp_boolean_expression(env)
3526 self.condition.release_temp(env)
3527 self.body.analyse_expressions(env)
3529 def generate_execution_code(self, code, end_label):
3530 self.condition.generate_evaluation_code(code)
3531 code.putln(
3532 "if (%s) {" %
3533 self.condition.result())
3534 self.body.generate_execution_code(code)
3535 #code.putln(
3536 # "goto %s;" %
3537 # end_label)
3538 code.put_goto(end_label)
3539 code.putln("}")
3541 def annotate(self, code):
3542 self.condition.annotate(code)
3543 self.body.annotate(code)
3546 class SwitchCaseNode(StatNode):
3547 # Generated in the optimization of an if-elif-else node
3548 #
3549 # conditions [ExprNode]
3550 # body StatNode
3552 child_attrs = ['conditions', 'body']
3554 def generate_execution_code(self, code):
3555 for cond in self.conditions:
3556 code.putln("case %s:" % cond.calculate_result_code())
3557 self.body.generate_execution_code(code)
3558 code.putln("break;")
3560 def annotate(self, code):
3561 for cond in self.conditions:
3562 cond.annotate(code)
3563 self.body.annotate(code)
3565 class SwitchStatNode(StatNode):
3566 # Generated in the optimization of an if-elif-else node
3567 #
3568 # test ExprNode
3569 # cases [SwitchCaseNode]
3570 # else_clause StatNode or None
3572 child_attrs = ['test', 'cases', 'else_clause']
3574 def generate_execution_code(self, code):
3575 code.putln("switch (%s) {" % self.test.calculate_result_code())
3576 for case in self.cases:
3577 case.generate_execution_code(code)
3578 if self.else_clause is not None:
3579 code.putln("default:")
3580 self.else_clause.generate_execution_code(code)
3581 code.putln("break;")
3582 code.putln("}")
3584 def annotate(self, code):
3585 self.test.annotate(code)
3586 for case in self.cases:
3587 case.annotate(code)
3588 if self.else_clause is not None:
3589 self.else_clause.annotate(code)
3591 class LoopNode:
3593 def analyse_control_flow(self, env):
3594 env.start_branching(self.pos)
3595 self.body.analyse_control_flow(env)
3596 env.next_branch(self.body.end_pos())
3597 if self.else_clause:
3598 self.else_clause.analyse_control_flow(env)
3599 env.finish_branching(self.end_pos())
3602 class WhileStatNode(LoopNode, StatNode):
3603 # while statement
3604 #
3605 # condition ExprNode
3606 # body StatNode
3607 # else_clause StatNode
3609 child_attrs = ["condition", "body", "else_clause"]
3611 def analyse_declarations(self, env):
3612 self.body.analyse_declarations(env)
3613 if self.else_clause:
3614 self.else_clause.analyse_declarations(env)
3616 def analyse_expressions(self, env):
3617 self.condition = \
3618 self.condition.analyse_temp_boolean_expression(env)
3619 self.condition.release_temp(env)
3620 #env.recycle_pending_temps() # TEMPORARY
3621 self.body.analyse_expressions(env)
3622 if self.else_clause:
3623 self.else_clause.analyse_expressions(env)
3625 def generate_execution_code(self, code):
3626 old_loop_labels = code.new_loop_labels()
3627 code.putln(
3628 "while (1) {")
3629 self.condition.generate_evaluation_code(code)
3630 code.putln(
3631 "if (!%s) break;" %
3632 self.condition.result())
3633 self.body.generate_execution_code(code)
3634 code.put_label(code.continue_label)
3635 code.putln("}")
3636 break_label = code.break_label
3637 code.set_loop_labels(old_loop_labels)
3638 if self.else_clause:
3639 code.putln("/*else*/ {")
3640 self.else_clause.generate_execution_code(code)
3641 code.putln("}")
3642 code.put_label(break_label)
3644 def annotate(self, code):
3645 self.condition.annotate(code)
3646 self.body.annotate(code)
3647 if self.else_clause:
3648 self.else_clause.annotate(code)
3651 def ForStatNode(pos, **kw):
3652 if kw.has_key('iterator'):
3653 return ForInStatNode(pos, **kw)
3654 else:
3655 return ForFromStatNode(pos, **kw)
3657 class ForInStatNode(LoopNode, StatNode):
3658 # for statement
3659 #
3660 # target ExprNode
3661 # iterator IteratorNode
3662 # body StatNode
3663 # else_clause StatNode
3664 # item NextNode used internally
3666 child_attrs = ["target", "iterator", "body", "else_clause"]
3667 item = None
3669 def analyse_declarations(self, env):
3670 self.target.analyse_target_declaration(env)
3671 self.body.analyse_declarations(env)
3672 if self.else_clause:
3673 self.else_clause.analyse_declarations(env)
3675 def analyse_range_step(self, args):
3676 import ExprNodes
3677 # The direction must be determined at compile time to set relations.
3678 # Otherwise, return False.
3679 if len(args) < 3:
3680 self.step = ExprNodes.IntNode(pos = args[0].pos, value='1')
3681 self.relation1 = '<='
3682 self.relation2 = '<'
3683 return True
3684 else:
3685 step = args[2]
3686 if isinstance(step, ExprNodes.UnaryMinusNode) and isinstance(step.operand, ExprNodes.IntNode):
3687 step = ExprNodes.IntNode(pos = step.pos, value=str(-int(step.operand.value, 0)))
3688 if isinstance(step, ExprNodes.IntNode):
3689 step_value = int(step.value, 0)
3690 if step_value > 0:
3691 self.step = step
3692 self.relation1 = '<='
3693 self.relation2 = '<'
3694 return True
3695 elif step_value < 0:
3696 self.step = ExprNodes.IntNode(pos = step.pos, value=str(-step_value))
3697 self.relation1 = '>='
3698 self.relation2 = '>'
3699 return True
3700 return False
3703 def analyse_expressions(self, env):
3704 import ExprNodes
3705 self.target.analyse_target_types(env)
3706 if Options.convert_range and self.target.type.is_int:
3707 sequence = self.iterator.sequence
3708 if isinstance(sequence, ExprNodes.SimpleCallNode) \
3709 and sequence.self is None \
3710 and isinstance(sequence.function, ExprNodes.NameNode) \
3711 and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
3712 args = sequence.args
3713 # Make sure we can determine direction from step
3714 if self.analyse_range_step(args):
3715 # Mutate to ForFrom loop type
3716 self.__class__ = ForFromStatNode
3717 if len(args) == 1:
3718 self.bound1 = ExprNodes.IntNode(pos = sequence.pos, value='0')
3719 self.bound2 = args[0]
3720 else:
3721 self.bound1 = args[0]
3722 self.bound2 = args[1]
3723 ForFromStatNode.analyse_expressions(self, env)
3724 return
3726 self.iterator.analyse_expressions(env)
3727 self.item = ExprNodes.NextNode(self.iterator, env)
3728 self.item = self.item.coerce_to(self.target.type, env)
3729 self.item.allocate_temps(env)
3730 self.target.allocate_target_temps(env, self.item)
3731 #self.item.release_temp(env)
3732 #self.target.release_target_temp(env)
3733 self.body.analyse_expressions(env)
3734 if self.else_clause:
3735 self.else_clause.analyse_expressions(env)
3736 self.iterator.release_temp(env)
3738 def generate_execution_code(self, code):
3739 old_loop_labels = code.new_loop_labels()
3740 self.iterator.generate_evaluation_code(code)
3741 code.putln(
3742 "for (;;) {")
3743 self.item.generate_evaluation_code(code)
3744 self.target.generate_assignment_code(self.item, code)
3745 self.body.generate_execution_code(code)
3746 code.put_label(code.continue_label)
3747 code.putln(
3748 "}")
3749 break_label = code.break_label
3750 code.set_loop_labels(old_loop_labels)
3751 if self.else_clause:
3752 code.putln("/*else*/ {")
3753 self.else_clause.generate_execution_code(code)
3754 code.putln("}")
3755 code.put_label(break_label)
3756 self.iterator.generate_disposal_code(code)
3758 def annotate(self, code):
3759 self.target.annotate(code)
3760 self.iterator.annotate(code)
3761 self.body.annotate(code)
3762 if self.else_clause:
3763 self.else_clause.annotate(code)
3764 self.item.annotate(code)
3767 class ForFromStatNode(LoopNode, StatNode):
3768 # for name from expr rel name rel expr
3769 #
3770 # target NameNode
3771 # bound1 ExprNode
3772 # relation1 string
3773 # relation2 string
3774 # bound2 ExprNode
3775 # step ExprNode or None
3776 # body StatNode
3777 # else_clause StatNode or None
3778 #
3779 # Used internally:
3780 #
3781 # is_py_target bool
3782 # loopvar_name string
3783 # py_loopvar_node PyTempNode or None
3784 child_attrs = ["target", "bound1", "bound2", "step", "body", "else_clause"]
3786 def analyse_declarations(self, env):
3787 self.target.analyse_target_declaration(env)
3788 self.body.analyse_declarations(env)
3789 if self.else_clause:
3790 self.else_clause.analyse_declarations(env)
3792 def analyse_expressions(self, env):
3793 import ExprNodes
3794 self.target.analyse_target_types(env)
3795 self.bound1.analyse_types(env)
3796 self.bound2.analyse_types(env)
3797 if self.target.type.is_numeric:
3798 self.bound1 = self.bound1.coerce_to(self.target.type, env)
3799 self.bound2 = self.bound2.coerce_to(self.target.type, env)
3800 else:
3801 self.bound1 = self.bound1.coerce_to_integer(env)
3802 self.bound2 = self.bound2.coerce_to_integer(env)
3803 if self.step is not None:
3804 if isinstance(self.step, ExprNodes.UnaryMinusNode):
3805 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
3806 self.step.analyse_types(env)
3807 self.step = self.step.coerce_to_integer(env)
3808 if not (self.bound2.is_name or self.bound2.is_literal):
3809 self.bound2 = self.bound2.coerce_to_temp(env)
3810 target_type = self.target.type
3811 if not (target_type.is_pyobject or target_type.is_numeric):
3812 error(self.target.pos,
3813 "Integer for-loop variable must be of type int or Python object")
3814 #if not (target_type.is_pyobject
3815 # or target_type.assignable_from(PyrexTypes.c_int_type)):
3816 # error(self.target.pos,
3817 # "Cannot assign integer to variable of type '%s'" % target_type)
3818 if target_type.is_numeric:
3819 self.is_py_target = 0
3820 if isinstance(self.target, ExprNodes.IndexNode) and self.target.is_buffer_access:
3821 raise error(self.pos, "Buffer indexing not allowed as for loop target.")
3822 self.loopvar_name = self.target.entry.cname
3823 self.py_loopvar_node = None
3824 else:
3825 self.is_py_target = 1
3826 c_loopvar_node = ExprNodes.TempNode(self.pos,
3827 PyrexTypes.c_long_type, env)
3828 c_loopvar_node.allocate_temps(env)
3829 self.loopvar_name = c_loopvar_node.result()
3830 self.py_loopvar_node = \
3831 ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env)
3832 self.bound1.allocate_temps(env)
3833 self.bound2.allocate_temps(env)
3834 if self.step is not None:
3835 self.step.allocate_temps(env)
3836 if self.is_py_target:
3837 self.py_loopvar_node.allocate_temps(env)
3838 self.target.allocate_target_temps(env, self.py_loopvar_node)
3839 #self.target.release_target_temp(env)
3840 #self.py_loopvar_node.release_temp(env)
3841 self.body.analyse_expressions(env)
3842 if self.is_py_target:
3843 c_loopvar_node.release_temp(env)
3844 if self.else_clause:
3845 self.else_clause.analyse_expressions(env)
3846 self.bound1.release_temp(env)
3847 self.bound2.release_temp(env)
3848 if self.step is not None:
3849 self.step.release_temp(env)
3851 def generate_execution_code(self, code):
3852 old_loop_labels = code.new_loop_labels()
3853 self.bound1.generate_evaluation_code(code)
3854 self.bound2.generate_evaluation_code(code)
3855 offset, incop = self.relation_table[self.relation1]
3856 if self.step is not None:
3857 self.step.generate_evaluation_code(code)
3858 incop = "%s=%s" % (incop[0], self.step.result())
3859 code.putln(
3860 "for (%s = %s%s; %s %s %s; %s%s) {" % (
3861 self.loopvar_name,
3862 self.bound1.result(), offset,
3863 self.loopvar_name, self.relation2, self.bound2.result(),
3864 self.loopvar_name, incop))
3865 if self.py_loopvar_node:
3866 self.py_loopvar_node.generate_evaluation_code(code)
3867 self.target.generate_assignment_code(self.py_loopvar_node, code)
3868 self.body.generate_execution_code(code)
3869 code.put_label(code.continue_label)
3870 code.putln("}")
3871 break_label = code.break_label
3872 code.set_loop_labels(old_loop_labels)
3873 if self.else_clause:
3874 code.putln("/*else*/ {")
3875 self.else_clause.generate_execution_code(code)
3876 code.putln("}")
3877 code.put_label(break_label)
3878 self.bound1.generate_disposal_code(code)
3879 self.bound2.generate_disposal_code(code)
3880 if self.step is not None:
3881 self.step.generate_disposal_code(code)
3883 relation_table = {
3884 # {relop : (initial offset, increment op)}
3885 '<=': ("", "++"),
3886 '<' : ("+1", "++"),
3887 '>=': ("", "--"),
3888 '>' : ("-1", "--")
3889 }
3891 def annotate(self, code):
3892 self.target.annotate(code)
3893 self.bound1.annotate(code)
3894 self.bound2.annotate(code)
3895 if self.step:
3896 self.bound2.annotate(code)
3897 self.body.annotate(code)
3898 if self.else_clause:
3899 self.else_clause.annotate(code)
3902 class WithStatNode(StatNode):
3903 """
3904 Represents a Python with statement.
3906 This is only used at parse tree level; and is not present in
3907 analysis or generation phases.
3908 """
3909 # manager The with statement manager object
3910 # target Node (lhs expression)
3911 # body StatNode
3912 child_attrs = ["manager", "target", "body"]
3914 class TryExceptStatNode(StatNode):
3915 # try .. except statement
3916 #
3917 # body StatNode
3918 # except_clauses [ExceptClauseNode]
3919 # else_clause StatNode or None
3920 # cleanup_list [Entry] temps to clean up on error
3922 child_attrs = ["body", "except_clauses", "else_clause"]
3924 def analyse_control_flow(self, env):
3925 env.start_branching(self.pos)
3926 self.body.analyse_control_flow(env)
3927 successful_try = env.control_flow # grab this for later
3928 env.next_branch(self.body.end_pos())
3929 env.finish_branching(self.body.end_pos())
3931 env.start_branching(self.except_clauses[0].pos)
3932 for except_clause in self.except_clauses:
3933 except_clause.analyse_control_flow(env)
3934 env.next_branch(except_clause.end_pos())
3936 # the else cause it executed only when the try clause finishes
3937 env.control_flow.incoming = successful_try
3938 if self.else_clause:
3939 self.else_clause.analyse_control_flow(env)
3940 env.finish_branching(self.end_pos())
3942 def analyse_declarations(self, env):
3943 self.body.analyse_declarations(env)
3944 for except_clause in self.except_clauses:
3945 except_clause.analyse_declarations(env)
3946 if self.else_clause:
3947 self.else_clause.analyse_declarations(env)
3948 self.gil_check(env)
3949 env.use_utility_code(reset_exception_utility_code)
3951 def analyse_expressions(self, env):
3952 self.body.analyse_expressions(env)
3953 self.cleanup_list = env.free_temp_entries[:]
3954 default_clause_seen = 0
3955 for except_clause in self.except_clauses:
3956 except_clause.analyse_expressions(env)
3957 if default_clause_seen:
3958 error(except_clause.pos, "default 'except:' must be last")
3959 if not except_clause.pattern:
3960 default_clause_seen = 1
3961 self.has_default_clause = default_clause_seen
3962 if self.else_clause:
3963 self.else_clause.analyse_expressions(env)
3964 self.gil_check(env)
3966 gil_message = "Try-except statement"
3968 def generate_execution_code(self, code):
3969 old_return_label = code.return_label
3970 old_error_label = code.new_error_label()
3971 our_error_label = code.error_label
3972 except_end_label = code.new_label('exception_handled')
3973 except_error_label = code.new_label('except_error')
3974 except_return_label = code.new_label('except_return')
3975 try_end_label = code.new_label('try')
3977 code.putln("{")
3978 code.putln("PyObject %s;" %
3979 ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
3980 code.putln("__Pyx_ExceptionSave(%s);" %
3981 ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
3982 code.putln(
3983 "/*try:*/ {")
3984 self.body.generate_execution_code(code)
3985 code.putln(
3986 "}")
3987 code.error_label = except_error_label
3988 code.return_label = except_return_label
3989 if self.else_clause:
3990 code.putln(
3991 "/*else:*/ {")
3992 self.else_clause.generate_execution_code(code)
3993 code.putln(
3994 "}")
3995 for var in Naming.exc_save_vars:
3996 code.put_xdecref_clear(var, py_object_type)
3997 code.put_goto(try_end_label)
3998 code.put_label(our_error_label)
3999 code.put_var_xdecrefs_clear(self.cleanup_list)
4000 for except_clause in self.except_clauses:
4001 except_clause.generate_handling_code(code, except_end_label)
4003 error_label_used = code.label_used(except_error_label)
4004 if error_label_used or not self.has_default_clause:
4005 if error_label_used:
4006 code.put_label(except_error_label)
4007 for var in Naming.exc_save_vars:
4008 code.put_xdecref(var, py_object_type)
4009 code.put_goto(old_error_label)
4011 if code.label_used(except_return_label):
4012 code.put_label(except_return_label)
4013 code.putln("__Pyx_ExceptionReset(%s);" %
4014 ', '.join(Naming.exc_save_vars))
4015 code.put_goto(old_return_label)
4017 if code.label_used(except_end_label):
4018 code.put_label(except_end_label)
4019 code.putln("__Pyx_ExceptionReset(%s);" %
4020 ', '.join(Naming.exc_save_vars))
4021 code.put_label(try_end_label)
4022 code.putln("}")
4024 code.return_label = old_return_label
4025 code.error_label = old_error_label
4027 def annotate(self, code):
4028 self.body.annotate(code)
4029 for except_node in self.except_clauses:
4030 except_node.annotate(code)
4031 if self.else_clause:
4032 self.else_clause.annotate(code)
4035 class ExceptClauseNode(Node):
4036 # Part of try ... except statement.
4037 #
4038 # pattern ExprNode
4039 # target ExprNode or None
4040 # body StatNode
4041 # excinfo_target NameNode or None optional target for exception info
4042 # match_flag string result of exception match
4043 # exc_value ExcValueNode used internally
4044 # function_name string qualified name of enclosing function
4045 # exc_vars (string * 3) local exception variables
4047 # excinfo_target is never set by the parser, but can be set by a transform
4048 # in order to extract more extensive information about the exception as a
4049 # sys.exc_info()-style tuple into a target variable
4051 child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
4053 exc_value = None
4054 excinfo_target = None
4056 def analyse_declarations(self, env):
4057 if self.target:
4058 self.target.analyse_target_declaration(env)
4059 if self.excinfo_target is not None:
4060 self.excinfo_target.analyse_target_declaration(env)
4061 self.body.analyse_declarations(env)
4063 def analyse_expressions(self, env):
4064 import ExprNodes
4065 genv = env.global_scope()
4066 self.function_name = env.qualified_name
4067 if self.pattern:
4068 self.pattern.analyse_expressions(env)
4069 self.pattern = self.pattern.coerce_to_pyobject(env)
4070 self.match_flag = env.allocate_temp(PyrexTypes.c_int_type)
4071 self.pattern.release_temp(env)
4072 env.release_temp(self.match_flag)
4073 self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)]
4074 if self.target:
4075 self.exc_value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[1])
4076 self.exc_value.allocate_temps(env)
4077 self.target.analyse_target_expression(env, self.exc_value)
4078 if self.excinfo_target is not None:
4079 import ExprNodes
4080 self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[
4081 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[0]),
4082 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[1]),
4083 ExprNodes.ExcValueNode(pos=self.pos, env=env, var=self.exc_vars[2])
4084 ])
4085 self.excinfo_tuple.analyse_expressions(env)
4086 self.excinfo_tuple.allocate_temps(env)
4087 self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple)
4089 self.body.analyse_expressions(env)
4090 for var in self.exc_vars:
4091 env.release_temp(var)
4092 env.use_utility_code(get_exception_utility_code)
4093 env.use_utility_code(restore_exception_utility_code)
4095 def generate_handling_code(self, code, end_label):
4096 code.mark_pos(self.pos)
4097 if self.pattern:
4098 self.pattern.generate_evaluation_code(code)
4099 code.putln(
4100 "%s = PyErr_ExceptionMatches(%s);" % (
4101 self.match_flag,
4102 self.pattern.py_result()))
4103 self.pattern.generate_disposal_code(code)
4104 code.putln(
4105 "if (%s) {" %
4106 self.match_flag)
4107 else:
4108 code.putln("/*except:*/ {")
4109 code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
4110 # We always have to fetch the exception value even if
4111 # there is no target, because this also normalises the
4112 # exception and stores it in the thread state.
4113 exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars)
4114 code.putln("if (__Pyx_GetException(%s) < 0) %s" % (exc_args,
4115 code.error_goto(self.pos)))
4116 if self.target:
4117 self.exc_value.generate_evaluation_code(code)
4118 self.target.generate_assignment_code(self.exc_value, code)
4119 if self.excinfo_target is not None:
4120 self.excinfo_tuple.generate_evaluation_code(code)
4121 self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code)
4123 old_exc_vars = code.funcstate.exc_vars
4124 code.funcstate.exc_vars = self.exc_vars
4125 self.body.generate_execution_code(code)
4126 code.funcstate.exc_vars = old_exc_vars
4127 for var in self.exc_vars:
4128 code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
4129 code.put_goto(end_label)
4130 code.putln(
4131 "}")
4133 def annotate(self, code):
4134 if self.pattern:
4135 self.pattern.annotate(code)
4136 if self.target:
4137 self.target.annotate(code)
4138 self.body.annotate(code)
4141 class TryFinallyStatNode(StatNode):
4142 # try ... finally statement
4143 #
4144 # body StatNode
4145 # finally_clause StatNode
4146 #
4147 # cleanup_list [Entry] temps to clean up on error
4148 #
4149 # The plan is that we funnel all continue, break
4150 # return and error gotos into the beginning of the
4151 # finally block, setting a variable to remember which
4152 # one we're doing. At the end of the finally block, we
4153 # switch on the variable to figure out where to go.
4154 # In addition, if we're doing an error, we save the
4155 # exception on entry to the finally block and restore
4156 # it on exit.
4158 child_attrs = ["body", "finally_clause"]
4160 preserve_exception = 1
4162 disallow_continue_in_try_finally = 0
4163 # There doesn't seem to be any point in disallowing
4164 # continue in the try block, since we have no problem
4165 # handling it.
4167 def create_analysed(pos, env, body, finally_clause):
4168 node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
4169 node.cleanup_list = []
4170 return node
4171 create_analysed = staticmethod(create_analysed)
4173 def analyse_control_flow(self, env):
4174 env.start_branching(self.pos)
4175 self.body.analyse_control_flow(env)
4176 env.next_branch(self.body.end_pos())
4177 env.finish_branching(self.body.end_pos())
4178 self.finally_clause.analyse_control_flow(env)
4180 def analyse_declarations(self, env):
4181 self.body.analyse_declarations(env)
4182 self.finally_clause.analyse_declarations(env)
4184 def analyse_expressions(self, env):
4185 self.body.analyse_expressions(env)
4186 self.cleanup_list = env.free_temp_entries[:]
4187 self.finally_clause.analyse_expressions(env)
4188 self.gil_check(env)
4190 gil_message = "Try-finally statement"
4192 def generate_execution_code(self, code):
4193 old_error_label = code.error_label
4194 old_labels = code.all_new_labels()
4195 new_labels = code.get_all_labels()
4196 new_error_label = code.error_label
4197 catch_label = code.new_label()
4198 code.putln(
4199 "/*try:*/ {")
4200 if self.disallow_continue_in_try_finally:
4201 was_in_try_finally = code.funcstate.in_try_finally
4202 code.funcstate.in_try_finally = 1
4203 self.body.generate_execution_code(code)
4204 if self.disallow_continue_in_try_finally:
4205 code.funcstate.in_try_finally = was_in_try_finally
4206 code.putln(
4207 "}")
4208 code.putln(
4209 "/*finally:*/ {")
4210 cases_used = []
4211 error_label_used = 0
4212 for i, new_label in enumerate(new_labels):
4213 if new_label in code.labels_used:
4214 cases_used.append(i)
4215 if new_label == new_error_label:
4216 error_label_used = 1
4217 error_label_case = i
4218 if cases_used:
4219 code.putln(
4220 "int __pyx_why;")
4221 if error_label_used and self.preserve_exception:
4222 code.putln(
4223 "PyObject *%s, *%s, *%s;" % Naming.exc_vars)
4224 code.putln(
4225 "int %s;" % Naming.exc_lineno_name)
4226 exc_var_init_zero = ''.join(["%s = 0; " % var for var in Naming.exc_vars])
4227 exc_var_init_zero += '%s = 0;' % Naming.exc_lineno_name
4228 code.putln(exc_var_init_zero)
4229 else:
4230 exc_var_init_zero = None
4231 code.use_label(catch_label)
4232 code.putln(
4233 "__pyx_why = 0; goto %s;" % catch_label)
4234 for i in cases_used:
4235 new_label = new_labels[i]
4236 #if new_label and new_label != "<try>":
4237 if new_label == new_error_label and self.preserve_exception:
4238 self.put_error_catcher(code,
4239 new_error_label, i+1, catch_label)
4240 else:
4241 code.put('%s: ' % new_label)
4242 if exc_var_init_zero:
4243 code.putln(exc_var_init_zero)
4244 code.putln("__pyx_why = %s; goto %s;" % (
4245 i+1,
4246 catch_label))
4247 code.put_label(catch_label)
4248 code.set_all_labels(old_labels)
4249 if error_label_used:
4250 code.new_error_label()
4251 finally_error_label = code.error_label
4252 self.finally_clause.generate_execution_code(code)
4253 if error_label_used:
4254 if finally_error_label in code.labels_used and self.preserve_exception:
4255 over_label = code.new_label()
4256 code.put_goto(over_label);
4257 code.put_label(finally_error_label)
4258 code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
4259 for var in Naming.exc_vars:
4260 code.putln("Py_XDECREF(%s);" % var)
4261 code.putln("}")
4262 code.put_goto(old_error_label)
4263 code.put_label(over_label)
4264 code.error_label = old_error_label
4265 if cases_used:
4266 code.putln(
4267 "switch (__pyx_why) {")
4268 for i in cases_used:
4269 old_label = old_labels[i]
4270 if old_label == old_error_label and self.preserve_exception:
4271 self.put_error_uncatcher(code, i+1, old_error_label)
4272 else:
4273 code.use_label(old_label)
4274 code.putln(
4275 "case %s: goto %s;" % (
4276 i+1,
4277 old_label))
4278 code.putln(
4279 "}")
4280 code.putln(
4281 "}")
4283 def put_error_catcher(self, code, error_label, i, catch_label):
4284 code.globalstate.use_utility_code(restore_exception_utility_code)
4285 code.putln(
4286 "%s: {" %
4287 error_label)
4288 code.putln(
4289 "__pyx_why = %s;" %
4290 i)
4291 code.put_var_xdecrefs_clear(self.cleanup_list)
4292 code.putln(
4293 "__Pyx_ErrFetch(&%s, &%s, &%s);" %
4294 Naming.exc_vars)
4295 code.putln(
4296 "%s = %s;" % (
4297 Naming.exc_lineno_name, Naming.lineno_cname))
4298 #code.putln(
4299 # "goto %s;" %
4300 # catch_label)
4301 code.put_goto(catch_label)
4302 code.putln(
4303 "}")
4305 def put_error_uncatcher(self, code, i, error_label):
4306 code.globalstate.use_utility_code(restore_exception_utility_code)
4307 code.putln(
4308 "case %s: {" %
4309 i)
4310 code.putln(
4311 "__Pyx_ErrRestore(%s, %s, %s);" %
4312 Naming.exc_vars)
4313 code.putln(
4314 "%s = %s;" % (
4315 Naming.lineno_cname, Naming.exc_lineno_name))
4316 for var in Naming.exc_vars:
4317 code.putln(
4318 "%s = 0;" %
4319 var)
4320 code.put_goto(error_label)
4321 code.putln(
4322 "}")
4324 def annotate(self, code):
4325 self.body.annotate(code)
4326 self.finally_clause.annotate(code)
4329 class GILStatNode(TryFinallyStatNode):
4330 # 'with gil' or 'with nogil' statement
4331 #
4332 # state string 'gil' or 'nogil'
4334 child_attrs = []
4336 preserve_exception = 0
4338 def __init__(self, pos, state, body):
4339 self.state = state
4340 TryFinallyStatNode.__init__(self, pos,
4341 body = body,
4342 finally_clause = GILExitNode(pos, state = state))
4344 def analyse_expressions(self, env):
4345 was_nogil = env.nogil
4346 env.nogil = 1
4347 TryFinallyStatNode.analyse_expressions(self, env)
4348 env.nogil = was_nogil
4350 def gil_check(self, env):
4351 pass
4353 def generate_execution_code(self, code):
4354 code.putln("/*with %s:*/ {" % self.state)
4355 if self.state == 'gil':
4356 code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
4357 else:
4358 code.putln("PyThreadState *_save;")
4359 code.putln("Py_UNBLOCK_THREADS")
4360 TryFinallyStatNode.generate_execution_code(self, code)
4361 code.putln("}")
4364 class GILExitNode(StatNode):
4365 # Used as the 'finally' block in a GILStatNode
4366 #
4367 # state string 'gil' or 'nogil'
4369 child_attrs = []
4371 def analyse_expressions(self, env):
4372 pass
4374 def generate_execution_code(self, code):
4375 if self.state == 'gil':
4376 code.putln("PyGILState_Release();")
4377 else:
4378 code.putln("Py_BLOCK_THREADS")
4381 class CImportStatNode(StatNode):
4382 # cimport statement
4383 #
4384 # module_name string Qualified name of module being imported
4385 # as_name string or None Name specified in "as" clause, if any
4387 child_attrs = []
4389 def analyse_declarations(self, env):
4390 if not env.is_module_scope:
4391 error(self.pos, "cimport only allowed at module level")
4392 return
4393 module_scope = env.find_module(self.module_name, self.pos)
4394 if "." in self.module_name:
4395 names = [EncodedString(name) for name in self.module_name.split(".")]
4396 top_name = names[0]
4397 top_module_scope = env.context.find_submodule(top_name)
4398 module_scope = top_module_scope
4399 for name in names[1:]:
4400 submodule_scope = module_scope.find_submodule(name)
4401 module_scope.declare_module(name, submodule_scope, self.pos)
4402 module_scope = submodule_scope
4403 if self.as_name:
4404 env.declare_module(self.as_name, module_scope, self.pos)
4405 else:
4406 env.declare_module(top_name, top_module_scope, self.pos)
4407 else:
4408 name = self.as_name or self.module_name
4409 env.declare_module(name, module_scope, self.pos)
4411 def analyse_expressions(self, env):
4412 pass
4414 def generate_execution_code(self, code):
4415 pass
4418 class FromCImportStatNode(StatNode):
4419 # from ... cimport statement
4420 #
4421 # module_name string Qualified name of module
4422 # imported_names [(pos, name, as_name, kind)] Names to be imported
4424 child_attrs = []
4426 def analyse_declarations(self, env):
4427 if not env.is_module_scope:
4428 error(self.pos, "cimport only allowed at module level")
4429 return
4430 module_scope = env.find_module(self.module_name, self.pos)
4431 env.add_imported_module(module_scope)
4432 for pos, name, as_name, kind in self.imported_names:
4433 if name == "*":
4434 for local_name, entry in module_scope.entries.items():
4435 env.add_imported_entry(local_name, entry, pos)
4436 else:
4437 entry = module_scope.lookup(name)
4438 if entry:
4439 if kind and not self.declaration_matches(entry, kind):
4440 entry.redeclared(pos)
4441 else:
4442 if kind == 'struct' or kind == 'union':
4443 entry = module_scope.declare_struct_or_union(name,
4444 kind = kind, scope = None, typedef_flag = 0, pos = pos)
4445 elif kind == 'class':
4446 entry = module_scope.declare_c_class(name, pos = pos,
4447 module_name = self.module_name)
4448 else:
4449 error(pos, "Name '%s' not declared in module '%s'"
4450 % (name, self.module_name))
4452 if entry:
4453 local_name = as_name or name
4454 env.add_imported_entry(local_name, entry, pos)
4456 def declaration_matches(self, entry, kind):
4457 if not entry.is_type:
4458 return 0
4459 type = entry.type
4460 if kind == 'class':
4461 if not type.is_extension_type:
4462 return 0
4463 else:
4464 if not type.is_struct_or_union:
4465 return 0
4466 if kind <> type.kind:
4467 return 0
4468 return 1
4470 def analyse_expressions(self, env):
4471 pass
4473 def generate_execution_code(self, code):
4474 pass
4477 class FromImportStatNode(StatNode):
4478 # from ... import statement
4479 #
4480 # module ImportNode
4481 # items [(string, NameNode)]
4482 # interned_items [(string, NameNode)]
4483 # item PyTempNode used internally
4484 # import_star boolean used internally
4486 child_attrs = ["module"]
4487 import_star = 0
4489 def analyse_declarations(self, env):
4490 for name, target in self.items:
4491 if name == "*":
4492 if not env.is_module_scope:
4493 error(self.pos, "import * only allowed at module level")
4494 return
4495 env.has_import_star = 1
4496 self.import_star = 1
4497 else:
4498 target.analyse_target_declaration(env)
4500 def analyse_expressions(self, env):
4501 import ExprNodes
4502 self.module.analyse_expressions(env)
4503 self.item = ExprNodes.PyTempNode(self.pos, env)
4504 self.item.allocate_temp(env)
4505 self.interned_items = []
4506 for name, target in self.items:
4507 if name == '*':
4508 for _, entry in env.entries.items():
4509 if not entry.is_type and entry.type.is_extension_type:
4510 env.use_utility_code(ExprNodes.type_test_utility_code)
4511 break
4512 else:
4513 entry = env.lookup(target.name)
4514 if entry.is_type and entry.type.name == name and entry.type.module_name == self.module.module_name.value:
4515 continue # already cimported
4516 self.interned_items.append(
4517 (env.intern_identifier(name), target))
4518 target.analyse_target_expression(env, None)
4519 #target.release_target_temp(env) # was release_temp ?!?
4520 self.module.release_temp(env)
4521 self.item.release_temp(env)
4523 def generate_execution_code(self, code):
4524 self.module.generate_evaluation_code(code)
4525 if self.import_star:
4526 code.putln(
4527 'if (%s(%s) < 0) %s;' % (
4528 Naming.import_star,
4529 self.module.py_result(),
4530 code.error_goto(self.pos)))
4531 for cname, target in self.interned_items:
4532 code.putln(
4533 '%s = PyObject_GetAttr(%s, %s); %s' % (
4534 self.item.result(),
4535 self.module.py_result(),
4536 cname,
4537 code.error_goto_if_null(self.item.result(), self.pos)))
4538 target.generate_assignment_code(self.item, code)
4539 self.module.generate_disposal_code(code)
4543 #------------------------------------------------------------------------------------
4544 #
4545 # Runtime support code
4546 #
4547 #------------------------------------------------------------------------------------
4549 utility_function_predeclarations = \
4550 """
4551 #ifdef __GNUC__
4552 #define INLINE __inline__
4553 #elif _WIN32
4554 #define INLINE __inline
4555 #else
4556 #define INLINE
4557 #endif
4559 typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
4561 """ + """
4563 static int %(skip_dispatch_cname)s = 0;
4565 """ % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
4567 if Options.gcc_branch_hints:
4568 branch_prediction_macros = \
4569 """
4570 #ifdef __GNUC__
4571 /* Test for GCC > 2.95 */
4572 #if __GNUC__ > 2 || \
4573 (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
4574 #define likely(x) __builtin_expect(!!(x), 1)
4575 #define unlikely(x) __builtin_expect(!!(x), 0)
4576 #else /* __GNUC__ > 2 ... */
4577 #define likely(x) (x)
4578 #define unlikely(x) (x)
4579 #endif /* __GNUC__ > 2 ... */
4580 #else /* __GNUC__ */
4581 #define likely(x) (x)
4582 #define unlikely(x) (x)
4583 #endif /* __GNUC__ */
4584 """
4585 else:
4586 branch_prediction_macros = \
4587 """
4588 #define likely(x) (x)
4589 #define unlikely(x) (x)
4590 """
4592 #get_name_predeclaration = \
4593 #"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/"
4595 #get_name_interned_predeclaration = \
4596 #"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/"
4598 #------------------------------------------------------------------------------------
4600 printing_utility_code = UtilityCode(
4601 proto = """
4602 static int __Pyx_Print(PyObject *, int); /*proto*/
4603 #if PY_MAJOR_VERSION >= 3
4604 static PyObject* %s = 0;
4605 static PyObject* %s = 0;
4606 #endif
4607 """ % (Naming.print_function, Naming.print_function_kwargs),
4608 impl = r"""
4609 #if PY_MAJOR_VERSION < 3
4610 static PyObject *__Pyx_GetStdout(void) {
4611 PyObject *f = PySys_GetObject((char *)"stdout");
4612 if (!f) {
4613 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
4614 }
4615 return f;
4616 }
4618 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4619 PyObject *f;
4620 PyObject* v;
4621 int i;
4623 if (!(f = __Pyx_GetStdout()))
4624 return -1;
4625 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
4626 if (PyFile_SoftSpace(f, 1)) {
4627 if (PyFile_WriteString(" ", f) < 0)
4628 return -1;
4629 }
4630 v = PyTuple_GET_ITEM(arg_tuple, i);
4631 if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
4632 return -1;
4633 if (PyString_Check(v)) {
4634 char *s = PyString_AsString(v);
4635 Py_ssize_t len = PyString_Size(v);
4636 if (len > 0 &&
4637 isspace(Py_CHARMASK(s[len-1])) &&
4638 s[len-1] != ' ')
4639 PyFile_SoftSpace(f, 0);
4640 }
4641 }
4642 if (newline) {
4643 if (PyFile_WriteString("\n", f) < 0)
4644 return -1;
4645 PyFile_SoftSpace(f, 0);
4646 }
4647 return 0;
4648 }
4650 #else /* Python 3 has a print function */
4651 static int __Pyx_Print(PyObject *arg_tuple, int newline) {
4652 PyObject* kwargs = 0;
4653 PyObject* result = 0;
4654 PyObject* end_string;
4655 if (!%(PRINT_FUNCTION)s) {
4656 %(PRINT_FUNCTION)s = PyObject_GetAttrString(%(BUILTINS)s, "print");
4657 if (!%(PRINT_FUNCTION)s)
4658 return -1;
4659 }
4660 if (!newline) {
4661 if (!%(PRINT_KWARGS)s) {
4662 %(PRINT_KWARGS)s = PyDict_New();
4663 if (!%(PRINT_KWARGS)s)
4664 return -1;
4665 end_string = PyUnicode_FromStringAndSize(" ", 1);
4666 if (!end_string)
4667 return -1;
4668 if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
4669 Py_DECREF(end_string);
4670 return -1;
4671 }
4672 Py_DECREF(end_string);
4673 }
4674 kwargs = %(PRINT_KWARGS)s;
4675 }
4676 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
4677 if (!result)
4678 return -1;
4679 Py_DECREF(result);
4680 return 0;
4681 }
4682 #endif
4683 """ % {'BUILTINS' : Naming.builtins_cname,
4684 'PRINT_FUNCTION' : Naming.print_function,
4685 'PRINT_KWARGS' : Naming.print_function_kwargs}
4686 )
4688 #------------------------------------------------------------------------------------
4690 # The following function is based on do_raise() from ceval.c.
4692 raise_utility_code = UtilityCode(
4693 proto = """
4694 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
4695 """,
4696 impl = """
4697 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
4698 Py_XINCREF(type);
4699 Py_XINCREF(value);
4700 Py_XINCREF(tb);
4701 /* First, check the traceback argument, replacing None with NULL. */
4702 if (tb == Py_None) {
4703 Py_DECREF(tb);
4704 tb = 0;
4705 }
4706 else if (tb != NULL && !PyTraceBack_Check(tb)) {
4707 PyErr_SetString(PyExc_TypeError,
4708 "raise: arg 3 must be a traceback or None");
4709 goto raise_error;
4710 }
4711 /* Next, replace a missing value with None */
4712 if (value == NULL) {
4713 value = Py_None;
4714 Py_INCREF(value);
4715 }
4716 #if PY_VERSION_HEX < 0x02050000
4717 if (!PyClass_Check(type))
4718 #else
4719 if (!PyType_Check(type))
4720 #endif
4721 {
4722 /* Raising an instance. The value should be a dummy. */
4723 if (value != Py_None) {
4724 PyErr_SetString(PyExc_TypeError,
4725 "instance exception may not have a separate value");
4726 goto raise_error;
4727 }
4728 /* Normalize to raise <class>, <instance> */
4729 Py_DECREF(value);
4730 value = type;
4731 #if PY_VERSION_HEX < 0x02050000
4732 if (PyInstance_Check(type)) {
4733 type = (PyObject*) ((PyInstanceObject*)type)->in_class;
4734 Py_INCREF(type);
4735 }
4736 else {
4737 type = 0;
4738 PyErr_SetString(PyExc_TypeError,
4739 "raise: exception must be an old-style class or instance");
4740 goto raise_error;
4741 }
4742 #else
4743 type = (PyObject*) Py_TYPE(type);
4744 Py_INCREF(type);
4745 if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
4746 PyErr_SetString(PyExc_TypeError,
4747 "raise: exception class must be a subclass of BaseException");
4748 goto raise_error;
4749 }
4750 #endif
4751 }
4752 __Pyx_ErrRestore(type, value, tb);
4753 return;
4754 raise_error:
4755 Py_XDECREF(value);
4756 Py_XDECREF(type);
4757 Py_XDECREF(tb);
4758 return;
4759 }
4760 """)
4762 #------------------------------------------------------------------------------------
4764 reraise_utility_code = UtilityCode(
4765 proto = """
4766 static void __Pyx_ReRaise(void); /*proto*/
4767 """,
4768 impl = """
4769 static void __Pyx_ReRaise(void) {
4770 PyThreadState *tstate = PyThreadState_Get();
4771 PyObject *type = tstate->exc_type;
4772 PyObject *value = tstate->exc_value;
4773 PyObject *tb = tstate->exc_traceback;
4774 Py_XINCREF(type);
4775 Py_XINCREF(value);
4776 Py_XINCREF(tb);
4777 __Pyx_ErrRestore(type, value, tb);
4778 }
4779 """)
4781 #------------------------------------------------------------------------------------
4783 arg_type_test_utility_code = UtilityCode(
4784 proto = """
4785 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4786 const char *name, int exact); /*proto*/
4787 """,
4788 impl = """
4789 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
4790 const char *name, int exact)
4791 {
4792 if (!type) {
4793 PyErr_Format(PyExc_SystemError, "Missing type object");
4794 return 0;
4795 }
4796 if (none_allowed && obj == Py_None) return 1;
4797 else if (exact) {
4798 if (Py_TYPE(obj) == type) return 1;
4799 }
4800 else {
4801 if (PyObject_TypeCheck(obj, type)) return 1;
4802 }
4803 PyErr_Format(PyExc_TypeError,
4804 "Argument '%s' has incorrect type (expected %s, got %s)",
4805 name, type->tp_name, Py_TYPE(obj)->tp_name);
4806 return 0;
4807 }
4808 """)
4810 #------------------------------------------------------------------------------------
4811 #
4812 # __Pyx_RaiseArgtupleInvalid raises the correct exception when too
4813 # many or too few positional arguments were found. This handles
4814 # Py_ssize_t formatting correctly.
4816 raise_argtuple_invalid_utility_code = UtilityCode(
4817 proto = """
4818 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
4819 Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
4820 """,
4821 impl = """
4822 static void __Pyx_RaiseArgtupleInvalid(
4823 const char* func_name,
4824 int exact,
4825 Py_ssize_t num_min,
4826 Py_ssize_t num_max,
4827 Py_ssize_t num_found)
4828 {
4829 Py_ssize_t num_expected;
4830 const char *number, *more_or_less;
4832 if (num_found < num_min) {
4833 num_expected = num_min;
4834 more_or_less = "at least";
4835 } else {
4836 num_expected = num_max;
4837 more_or_less = "at most";
4838 }
4839 if (exact) {
4840 more_or_less = "exactly";
4841 }
4842 number = (num_expected == 1) ? "" : "s";
4843 PyErr_Format(PyExc_TypeError,
4844 #if PY_VERSION_HEX < 0x02050000
4845 "%s() takes %s %d positional argument%s (%d given)",
4846 #else
4847 "%s() takes %s %zd positional argument%s (%zd given)",
4848 #endif
4849 func_name, more_or_less, num_expected, number, num_found);
4850 }
4851 """)
4853 raise_keyword_required_utility_code = UtilityCode(
4854 proto = """
4855 static INLINE void __Pyx_RaiseKeywordRequired(const char* func_name, PyObject* kw_name); /*proto*/
4856 """,
4857 impl = """
4858 static INLINE void __Pyx_RaiseKeywordRequired(
4859 const char* func_name,
4860 PyObject* kw_name)
4861 {
4862 PyErr_Format(PyExc_TypeError,
4863 #if PY_MAJOR_VERSION >= 3
4864 "%s() needs keyword-only argument %U", func_name, kw_name);
4865 #else
4866 "%s() needs keyword-only argument %s", func_name,
4867 PyString_AS_STRING(kw_name));
4868 #endif
4869 }
4870 """)
4872 raise_double_keywords_utility_code = UtilityCode(
4873 proto = """
4874 static void __Pyx_RaiseDoubleKeywordsError(
4875 const char* func_name, PyObject* kw_name); /*proto*/
4876 """,
4877 impl = """
4878 static void __Pyx_RaiseDoubleKeywordsError(
4879 const char* func_name,
4880 PyObject* kw_name)
4881 {
4882 PyErr_Format(PyExc_TypeError,
4883 #if PY_MAJOR_VERSION >= 3
4884 "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
4885 #else
4886 "%s() got multiple values for keyword argument '%s'", func_name,
4887 PyString_AS_STRING(kw_name));
4888 #endif
4889 }
4890 """)
4892 #------------------------------------------------------------------------------------
4893 #
4894 # __Pyx_CheckKeywordStrings raises an error if non-string keywords
4895 # were passed to a function, or if any keywords were passed to a
4896 # function that does not accept them.
4898 keyword_string_check_utility_code = UtilityCode(
4899 proto = """
4900 static INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict,
4901 const char* function_name, int kw_allowed); /*proto*/
4902 """,
4903 impl = """
4904 static INLINE int __Pyx_CheckKeywordStrings(
4905 PyObject *kwdict,
4906 const char* function_name,
4907 int kw_allowed)
4908 {
4909 PyObject* key = 0;
4910 Py_ssize_t pos = 0;
4911 while (PyDict_Next(kwdict, &pos, &key, 0)) {
4912 #if PY_MAJOR_VERSION < 3
4913 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
4914 #else
4915 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key)))
4916 #endif
4917 goto invalid_keyword_type;
4918 }
4919 if ((!kw_allowed) && unlikely(key))
4920 goto invalid_keyword;
4921 return 1;
4922 invalid_keyword_type:
4923 PyErr_Format(PyExc_TypeError,
4924 "%s() keywords must be strings", function_name);
4925 return 0;
4926 invalid_keyword:
4927 PyErr_Format(PyExc_TypeError,
4928 #if PY_MAJOR_VERSION < 3
4929 "%s() got an unexpected keyword argument '%s'",
4930 function_name, PyString_AsString(key));
4931 #else
4932 "%s() got an unexpected keyword argument '%U'",
4933 function_name, key);
4934 #endif
4935 return 0;
4936 }
4937 """)
4939 #------------------------------------------------------------------------------------
4940 #
4941 # __Pyx_ParseOptionalKeywords copies the optional/unknown keyword
4942 # arguments from the kwds dict into kwds2. If kwds2 is NULL, unknown
4943 # keywords will raise an invalid keyword error.
4944 #
4945 # Three kinds of errors are checked: 1) non-string keywords, 2)
4946 # unexpected keywords and 3) overlap with positional arguments.
4947 #
4948 # If num_posargs is greater 0, it denotes the number of positional
4949 # arguments that were passed and that must therefore not appear
4950 # amongst the keywords as well.
4951 #
4952 # This method does not check for required keyword arguments.
4953 #
4955 parse_keywords_utility_code = UtilityCode(
4956 proto = """
4957 static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
4958 PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
4959 const char* function_name); /*proto*/
4960 """,
4961 impl = """
4962 static int __Pyx_ParseOptionalKeywords(
4963 PyObject *kwds,
4964 PyObject **argnames[],
4965 PyObject *kwds2,
4966 PyObject *values[],
4967 Py_ssize_t num_pos_args,
4968 const char* function_name)
4969 {
4970 PyObject *key = 0, *value = 0;
4971 Py_ssize_t pos = 0;
4972 PyObject*** name;
4973 PyObject*** first_kw_arg = argnames + num_pos_args;
4975 while (PyDict_Next(kwds, &pos, &key, &value)) {
4976 #if PY_MAJOR_VERSION < 3
4977 if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key))) {
4978 #else
4979 if (unlikely(!PyUnicode_CheckExact(key)) && unlikely(!PyUnicode_Check(key))) {
4980 #endif
4981 goto invalid_keyword_type;
4982 } else {
4983 name = argnames;
4984 while (*name && (**name != key)) name++;
4985 if (*name) {
4986 if (name < first_kw_arg) goto arg_passed_twice;
4987 values[name-argnames] = value;
4988 } else {
4989 for (name = first_kw_arg; *name; name++) {
4990 #if PY_MAJOR_VERSION >= 3
4991 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
4992 PyUnicode_Compare(**name, key) == 0) break;
4993 #else
4994 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
4995 strcmp(PyString_AS_STRING(**name),
4996 PyString_AS_STRING(key)) == 0) break;
4997 #endif
4998 }
4999 if (*name) {
5000 values[name-argnames] = value;
5001 } else {
5002 /* unexpected keyword found */
5003 for (name=argnames; name != first_kw_arg; name++) {
5004 if (**name == key) goto arg_passed_twice;
5005 #if PY_MAJOR_VERSION >= 3
5006 if (PyUnicode_GET_SIZE(**name) == PyUnicode_GET_SIZE(key) &&
5007 PyUnicode_Compare(**name, key) == 0) goto arg_passed_twice;
5008 #else
5009 if (PyString_GET_SIZE(**name) == PyString_GET_SIZE(key) &&
5010 strcmp(PyString_AS_STRING(**name),
5011 PyString_AS_STRING(key)) == 0) goto arg_passed_twice;
5012 #endif
5013 }
5014 if (kwds2) {
5015 if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
5016 } else {
5017 goto invalid_keyword;
5018 }
5019 }
5020 }
5021 }
5022 }
5023 return 0;
5024 arg_passed_twice:
5025 __Pyx_RaiseDoubleKeywordsError(function_name, **name);
5026 goto bad;
5027 invalid_keyword_type:
5028 PyErr_Format(PyExc_TypeError,
5029 "%s() keywords must be strings", function_name);
5030 goto bad;
5031 invalid_keyword:
5032 PyErr_Format(PyExc_TypeError,
5033 #if PY_MAJOR_VERSION < 3
5034 "%s() got an unexpected keyword argument '%s'",
5035 function_name, PyString_AsString(key));
5036 #else
5037 "%s() got an unexpected keyword argument '%U'",
5038 function_name, key);
5039 #endif
5040 bad:
5041 return -1;
5042 }
5043 """)
5045 #------------------------------------------------------------------------------------
5047 unraisable_exception_utility_code = UtilityCode(
5048 proto = """
5049 static void __Pyx_WriteUnraisable(const char *name); /*proto*/
5050 """,
5051 impl = """
5052 static void __Pyx_WriteUnraisable(const char *name) {
5053 PyObject *old_exc, *old_val, *old_tb;
5054 PyObject *ctx;
5055 __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
5056 #if PY_MAJOR_VERSION < 3
5057 ctx = PyString_FromString(name);
5058 #else
5059 ctx = PyUnicode_FromString(name);
5060 #endif
5061 __Pyx_ErrRestore(old_exc, old_val, old_tb);
5062 if (!ctx) {
5063 PyErr_WriteUnraisable(Py_None);
5064 } else {
5065 PyErr_WriteUnraisable(ctx);
5066 Py_DECREF(ctx);
5067 }
5068 }
5069 """)
5071 #------------------------------------------------------------------------------------
5073 traceback_utility_code = UtilityCode(
5074 proto = """
5075 static void __Pyx_AddTraceback(const char *funcname); /*proto*/
5076 """,
5077 impl = """
5078 #include "compile.h"
5079 #include "frameobject.h"
5080 #include "traceback.h"
5082 static void __Pyx_AddTraceback(const char *funcname) {
5083 PyObject *py_srcfile = 0;
5084 PyObject *py_funcname = 0;
5085 PyObject *py_globals = 0;
5086 PyObject *empty_string = 0;
5087 PyCodeObject *py_code = 0;
5088 PyFrameObject *py_frame = 0;
5090 #if PY_MAJOR_VERSION < 3
5091 py_srcfile = PyString_FromString(%(FILENAME)s);
5092 #else
5093 py_srcfile = PyUnicode_FromString(%(FILENAME)s);
5094 #endif
5095 if (!py_srcfile) goto bad;
5096 if (%(CLINENO)s) {
5097 #if PY_MAJOR_VERSION < 3
5098 py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5099 #else
5100 py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
5101 #endif
5102 }
5103 else {
5104 #if PY_MAJOR_VERSION < 3
5105 py_funcname = PyString_FromString(funcname);
5106 #else
5107 py_funcname = PyUnicode_FromString(funcname);
5108 #endif
5109 }
5110 if (!py_funcname) goto bad;
5111 py_globals = PyModule_GetDict(%(GLOBALS)s);
5112 if (!py_globals) goto bad;
5113 #if PY_MAJOR_VERSION < 3
5114 empty_string = PyString_FromStringAndSize("", 0);
5115 #else
5116 empty_string = PyBytes_FromStringAndSize("", 0);
5117 #endif
5118 if (!empty_string) goto bad;
5119 py_code = PyCode_New(
5120 0, /*int argcount,*/
5121 #if PY_MAJOR_VERSION >= 3
5122 0, /*int kwonlyargcount,*/
5123 #endif
5124 0, /*int nlocals,*/
5125 0, /*int stacksize,*/
5126 0, /*int flags,*/
5127 empty_string, /*PyObject *code,*/
5128 %(EMPTY_TUPLE)s, /*PyObject *consts,*/
5129 %(EMPTY_TUPLE)s, /*PyObject *names,*/
5130 %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
5131 %(EMPTY_TUPLE)s, /*PyObject *freevars,*/
5132 %(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
5133 py_srcfile, /*PyObject *filename,*/
5134 py_funcname, /*PyObject *name,*/
5135 %(LINENO)s, /*int firstlineno,*/
5136 empty_string /*PyObject *lnotab*/
5137 );
5138 if (!py_code) goto bad;
5139 py_frame = PyFrame_New(
5140 PyThreadState_GET(), /*PyThreadState *tstate,*/
5141 py_code, /*PyCodeObject *code,*/
5142 py_globals, /*PyObject *globals,*/
5143 0 /*PyObject *locals*/
5144 );
5145 if (!py_frame) goto bad;
5146 py_frame->f_lineno = %(LINENO)s;
5147 PyTraceBack_Here(py_frame);
5148 bad:
5149 Py_XDECREF(py_srcfile);
5150 Py_XDECREF(py_funcname);
5151 Py_XDECREF(empty_string);
5152 Py_XDECREF(py_code);
5153 Py_XDECREF(py_frame);
5154 }
5155 """ % {
5156 'FILENAME': Naming.filename_cname,
5157 'LINENO': Naming.lineno_cname,
5158 'CFILENAME': Naming.cfilenm_cname,
5159 'CLINENO': Naming.clineno_cname,
5160 'GLOBALS': Naming.module_cname,
5161 'EMPTY_TUPLE' : Naming.empty_tuple,
5162 })
5164 restore_exception_utility_code = UtilityCode(
5165 proto = """
5166 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5167 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5168 """,
5169 impl = """
5170 static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
5171 PyObject *tmp_type, *tmp_value, *tmp_tb;
5172 PyThreadState *tstate = PyThreadState_GET();
5174 tmp_type = tstate->curexc_type;
5175 tmp_value = tstate->curexc_value;
5176 tmp_tb = tstate->curexc_traceback;
5177 tstate->curexc_type = type;
5178 tstate->curexc_value = value;
5179 tstate->curexc_traceback = tb;
5180 Py_XDECREF(tmp_type);
5181 Py_XDECREF(tmp_value);
5182 Py_XDECREF(tmp_tb);
5183 }
5185 static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
5186 PyThreadState *tstate = PyThreadState_GET();
5187 *type = tstate->curexc_type;
5188 *value = tstate->curexc_value;
5189 *tb = tstate->curexc_traceback;
5191 tstate->curexc_type = 0;
5192 tstate->curexc_value = 0;
5193 tstate->curexc_traceback = 0;
5194 }
5196 """)
5198 #------------------------------------------------------------------------------------
5200 set_vtable_utility_code = UtilityCode(
5201 proto = """
5202 static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
5203 """,
5204 impl = """
5205 static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
5206 PyObject *pycobj = 0;
5207 int result;
5209 pycobj = PyCObject_FromVoidPtr(vtable, 0);
5210 if (!pycobj)
5211 goto bad;
5212 if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
5213 goto bad;
5214 result = 0;
5215 goto done;
5217 bad:
5218 result = -1;
5219 done:
5220 Py_XDECREF(pycobj);
5221 return result;
5222 }
5223 """)
5225 #------------------------------------------------------------------------------------
5227 get_vtable_utility_code = UtilityCode(
5228 proto = """
5229 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
5230 """,
5231 impl = r"""
5232 static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
5233 int result;
5234 PyObject *pycobj;
5236 pycobj = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
5237 if (!pycobj)
5238 goto bad;
5239 *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj);
5240 if (!*(void **)vtabptr)
5241 goto bad;
5242 result = 0;
5243 goto done;
5245 bad:
5246 result = -1;
5247 done:
5248 Py_XDECREF(pycobj);
5249 return result;
5250 }
5251 """)
5253 #------------------------------------------------------------------------------------
5255 init_string_tab_utility_code = UtilityCode(
5256 proto = """
5257 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
5258 """,
5259 impl = """
5260 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
5261 while (t->p) {
5262 #if PY_MAJOR_VERSION < 3
5263 if (t->is_unicode && (!t->is_identifier)) {
5264 *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
5265 } else if (t->intern) {
5266 *t->p = PyString_InternFromString(t->s);
5267 } else {
5268 *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
5269 }
5270 #else /* Python 3+ has unicode identifiers */
5271 if (t->is_identifier || (t->is_unicode && t->intern)) {
5272 *t->p = PyUnicode_InternFromString(t->s);
5273 } else if (t->is_unicode) {
5274 *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
5275 } else {
5276 *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
5277 }
5278 #endif
5279 if (!*t->p)
5280 return -1;
5281 ++t;
5282 }
5283 return 0;
5284 }
5285 """)
5287 #------------------------------------------------------------------------------------
5289 get_exception_utility_code = UtilityCode(
5290 proto = """
5291 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5292 """,
5293 impl = """
5294 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
5295 PyObject *tmp_type, *tmp_value, *tmp_tb;
5296 PyThreadState *tstate = PyThreadState_GET();
5297 __Pyx_ErrFetch(type, value, tb);
5298 PyErr_NormalizeException(type, value, tb);
5299 if (PyErr_Occurred())
5300 goto bad;
5301 Py_INCREF(*type);
5302 Py_INCREF(*value);
5303 Py_INCREF(*tb);
5304 tmp_type = tstate->exc_type;
5305 tmp_value = tstate->exc_value;
5306 tmp_tb = tstate->exc_traceback;
5307 tstate->exc_type = *type;
5308 tstate->exc_value = *value;
5309 tstate->exc_traceback = *tb;
5310 /* Make sure tstate is in a consistent state when we XDECREF
5311 these objects (XDECREF may run arbitrary code). */
5312 Py_XDECREF(tmp_type);
5313 Py_XDECREF(tmp_value);
5314 Py_XDECREF(tmp_tb);
5315 return 0;
5316 bad:
5317 Py_XDECREF(*type);
5318 Py_XDECREF(*value);
5319 Py_XDECREF(*tb);
5320 return -1;
5321 }
5323 """)
5325 #------------------------------------------------------------------------------------
5327 reset_exception_utility_code = UtilityCode(
5328 proto = """
5329 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
5330 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
5331 """,
5332 impl = """
5333 static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
5334 PyThreadState *tstate = PyThreadState_GET();
5335 *type = tstate->exc_type;
5336 *value = tstate->exc_value;
5337 *tb = tstate->exc_traceback;
5338 Py_XINCREF(*type);
5339 Py_XINCREF(*value);
5340 Py_XINCREF(*tb);
5341 }
5343 static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
5344 PyObject *tmp_type, *tmp_value, *tmp_tb;
5345 PyThreadState *tstate = PyThreadState_GET();
5346 tmp_type = tstate->exc_type;
5347 tmp_value = tstate->exc_value;
5348 tmp_tb = tstate->exc_traceback;
5349 tstate->exc_type = type;
5350 tstate->exc_value = value;
5351 tstate->exc_traceback = tb;
5352 Py_XDECREF(tmp_type);
5353 Py_XDECREF(tmp_value);
5354 Py_XDECREF(tmp_tb);
5355 }
5356 """)
5358 #------------------------------------------------------------------------------------
